~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Devananda
  • Date: 2009-07-04 01:55:13 UTC
  • mto: (1086.10.1 length-plugin)
  • mto: This revision was merged to the branch mainline in revision 1095.
  • Revision ID: deva@myst-20090704015513-gtqliazxtfm7sdvf
refactored function/length into plugin/length

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
4
 
Copyright (C) 2009, Percona Inc.
5
 
 
6
 
Portions of this file contain modifications contributed and copyrighted
7
 
by Percona Inc.. Those modifications are
8
 
gratefully acknowledged and are described briefly in the InnoDB
9
 
documentation. The contributions by Percona Inc. are incorporated with
10
 
their permission, and subject to the conditions contained in the file
11
 
COPYING.Percona.
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
12
4
 
13
5
This program is free software; you can redistribute it and/or modify it under
14
6
the terms of the GNU General Public License as published by the Free Software
19
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20
12
 
21
13
You should have received a copy of the GNU General Public License along with
22
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
23
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
24
16
 
25
17
*****************************************************************************/
26
18
 
27
 
/**************************************************//**
28
 
@file os/os0file.c
 
19
/******************************************************
29
20
The interface to the operating system file i/o primitives
30
21
 
31
22
Created 10/21/1995 Heikki Tuuri
32
23
*******************************************************/
33
24
 
34
25
#include "os0file.h"
35
 
 
36
 
#ifdef UNIV_NONINL
37
 
#include "os0file.ic"
38
 
#endif
39
 
 
 
26
#include "os0sync.h"
 
27
#include "os0thread.h"
40
28
#include "ut0mem.h"
41
29
#include "srv0srv.h"
42
30
#include "srv0start.h"
43
31
#include "fil0fil.h"
44
32
#include "buf0buf.h"
 
33
 
 
34
#if defined(UNIV_HOTBACKUP) && defined(__WIN__)
 
35
/* Add includes for the _stat() call to compile on Windows */
 
36
#include <sys/types.h>
 
37
#include <sys/stat.h>
45
38
#include <errno.h>
46
 
#include <fcntl.h>
47
 
#include <limits.h>
48
 
#include <unistd.h>
49
 
#ifndef UNIV_HOTBACKUP
50
 
# include "os0sync.h"
51
 
# include "os0thread.h"
52
 
#else /* !UNIV_HOTBACKUP */
53
 
# ifdef __WIN__
54
 
/* Add includes for the _stat() call to compile on Windows */
55
 
#  include <sys/types.h>
56
 
#  include <sys/stat.h>
57
 
# endif /* __WIN__ */
58
 
#endif /* !UNIV_HOTBACKUP */
59
 
 
60
 
#if defined(LINUX_NATIVE_AIO)
61
 
#include <libaio.h>
62
 
#endif
 
39
#endif /* UNIV_HOTBACKUP */
63
40
 
64
41
/* This specifies the file permissions InnoDB uses when it creates files in
65
42
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
66
43
my_umask */
67
44
 
68
45
#ifndef __WIN__
69
 
/** Umask for creating files */
70
46
UNIV_INTERN ulint       os_innodb_umask
71
47
                        = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
72
48
#else
73
 
/** Umask for creating files */
74
49
UNIV_INTERN ulint       os_innodb_umask         = 0;
75
50
#endif
76
51
 
82
57
/* We do not call os_file_flush in every os_file_write. */
83
58
#endif /* UNIV_DO_FLUSH */
84
59
 
85
 
#ifndef UNIV_HOTBACKUP
86
60
/* We use these mutexes to protect lseek + file i/o operation, if the
87
61
OS does not provide an atomic pread or pwrite, or similar */
88
62
#define OS_FILE_N_SEEK_MUTEXES  16
91
65
/* In simulated aio, merge at most this many consecutive i/os */
92
66
#define OS_AIO_MERGE_N_CONSECUTIVE      64
93
67
 
94
 
/**********************************************************************
95
 
 
96
 
InnoDB AIO Implementation:
97
 
=========================
98
 
 
99
 
We support native AIO for windows and linux. For rest of the platforms
100
 
we simulate AIO by special io-threads servicing the IO-requests.
101
 
 
102
 
Simulated AIO:
103
 
==============
104
 
 
105
 
In platforms where we 'simulate' AIO following is a rough explanation
106
 
of the high level design.
107
 
There are four io-threads (for ibuf, log, read, write).
108
 
All synchronous IO requests are serviced by the calling thread using
109
 
os_file_write/os_file_read. The Asynchronous requests are queued up
110
 
in an array (there are four such arrays) by the calling thread. 
111
 
Later these requests are picked up by the io-thread and are serviced
112
 
synchronously.
113
 
 
114
 
Windows native AIO:
115
 
==================
116
 
 
117
 
If srv_use_native_aio is not set then windows follow the same
118
 
code as simulated AIO. If the flag is set then native AIO interface
119
 
is used. On windows, one of the limitation is that if a file is opened
120
 
for AIO no synchronous IO can be done on it. Therefore we have an
121
 
extra fifth array to queue up synchronous IO requests.
122
 
There are innodb_file_io_threads helper threads. These threads work
123
 
on the four arrays mentioned above in Simulated AIO. No thread is
124
 
required for the sync array.
125
 
If a synchronous IO request is made, it is first queued in the sync
126
 
array. Then the calling thread itself waits on the request, thus
127
 
making the call synchronous.
128
 
If an AIO request is made the calling thread not only queues it in the
129
 
array but also submits the requests. The helper thread then collects
130
 
the completed IO request and calls completion routine on it.
131
 
 
132
 
Linux native AIO:
133
 
=================
134
 
 
135
 
If we have libaio installed on the system and innodb_use_native_aio
136
 
is set to TRUE we follow the code path of native AIO, otherwise we
137
 
do simulated AIO.
138
 
There are innodb_file_io_threads helper threads. These threads work
139
 
on the four arrays mentioned above in Simulated AIO.
140
 
If a synchronous IO request is made, it is handled by calling
141
 
os_file_write/os_file_read.
142
 
If an AIO request is made the calling thread not only queues it in the
143
 
array but also submits the requests. The helper thread then collects
144
 
the completed IO request and calls completion routine on it.
145
 
 
146
 
**********************************************************************/
147
 
 
148
 
/** Flag: enable debug printout for asynchronous i/o */
 
68
/* If this flag is TRUE, then we will use the native aio of the
 
69
OS (provided we compiled Innobase with it in), otherwise we will
 
70
use simulated aio we build below with threads */
 
71
 
 
72
UNIV_INTERN ibool       os_aio_use_native_aio   = FALSE;
 
73
 
149
74
UNIV_INTERN ibool       os_aio_print_debug      = FALSE;
150
75
 
151
 
#ifdef UNIV_PFS_IO
152
 
/* Keys to register InnoDB I/O with performance schema */
153
 
UNIV_INTERN mysql_pfs_key_t  innodb_file_data_key;
154
 
UNIV_INTERN mysql_pfs_key_t  innodb_file_log_key;
155
 
UNIV_INTERN mysql_pfs_key_t  innodb_file_temp_key;
156
 
#endif /* UNIV_PFS_IO */
157
 
 
158
 
/** The asynchronous i/o array slot structure */
 
76
/* The aio array slot structure */
159
77
typedef struct os_aio_slot_struct       os_aio_slot_t;
160
78
 
161
 
/** The asynchronous i/o array slot structure */
162
79
struct os_aio_slot_struct{
163
 
        ibool           is_read;        /*!< TRUE if a read operation */
164
 
        ulint           pos;            /*!< index of the slot in the aio
 
80
        ibool           is_read;        /* TRUE if a read operation */
 
81
        ulint           pos;            /* index of the slot in the aio
165
82
                                        array */
166
 
        ibool           reserved;       /*!< TRUE if this slot is reserved */
167
 
        time_t          reservation_time;/*!< time when reserved */
168
 
        ulint           len;            /*!< length of the block to read or
 
83
        ibool           reserved;       /* TRUE if this slot is reserved */
 
84
        time_t          reservation_time;/* time when reserved */
 
85
        ulint           len;            /* length of the block to read or
169
86
                                        write */
170
 
        byte*           buf;            /*!< buffer used in i/o */
171
 
        ulint           type;           /*!< OS_FILE_READ or OS_FILE_WRITE */
172
 
        ulint           offset;         /*!< 32 low bits of file offset in
 
87
        byte*           buf;            /* buffer used in i/o */
 
88
        ulint           type;           /* OS_FILE_READ or OS_FILE_WRITE */
 
89
        ulint           offset;         /* 32 low bits of file offset in
173
90
                                        bytes */
174
 
        ulint           offset_high;    /*!< 32 high bits of file offset */
175
 
        os_file_t       file;           /*!< file where to read or write */
176
 
        const char*     name;           /*!< file name or path */
177
 
        ibool           io_already_done;/*!< used only in simulated aio:
 
91
        ulint           offset_high;    /* 32 high bits of file offset */
 
92
        os_file_t       file;           /* file where to read or write */
 
93
        const char*     name;           /* file name or path */
 
94
        ibool           io_already_done;/* used only in simulated aio:
178
95
                                        TRUE if the physical i/o already
179
96
                                        made and only the slot message
180
97
                                        needs to be passed to the caller
181
98
                                        of os_aio_simulated_handle */
182
 
        fil_node_t*     message1;       /*!< message which is given by the */
183
 
        void*           message2;       /*!< the requester of an aio operation
 
99
        fil_node_t*     message1;       /* message which is given by the */
 
100
        void*           message2;       /* the requester of an aio operation
184
101
                                        and which can be used to identify
185
102
                                        which pending aio operation was
186
103
                                        completed */
187
104
#ifdef WIN_ASYNC_IO
188
 
        HANDLE          handle;         /*!< handle object we need in the
 
105
        os_event_t      event;          /* event object we need in the
189
106
                                        OVERLAPPED struct */
190
 
        OVERLAPPED      control;        /*!< Windows control block for the
 
107
        OVERLAPPED      control;        /* Windows control block for the
191
108
                                        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
109
#endif
197
110
};
198
111
 
199
 
/** The asynchronous i/o array structure */
 
112
/* The aio array structure */
200
113
typedef struct os_aio_array_struct      os_aio_array_t;
201
114
 
202
 
/** The asynchronous i/o array structure */
203
115
struct os_aio_array_struct{
204
 
        os_mutex_t      mutex;  /*!< the mutex protecting the aio array */
205
 
        os_event_t      not_full;
206
 
                                /*!< The event which is set to the
207
 
                                signaled state when there is space in
208
 
                                the aio outside the ibuf segment */
209
 
        os_event_t      is_empty;
210
 
                                /*!< The event which is set to the
211
 
                                signaled state when there are no
212
 
                                pending i/os in this array */
213
 
        ulint           n_slots;/*!< Total number of slots in the aio
214
 
                                array.  This must be divisible by
215
 
                                n_threads. */
216
 
        ulint           n_segments;
217
 
                                /*!< Number of segments in the aio
218
 
                                array of pending aio requests. A
219
 
                                thread can wait separately for any one
220
 
                                of the segments. */
221
 
        ulint           cur_seg;/*!< We reserve IO requests in round
222
 
                                robin fashion to different segments.
223
 
                                This points to the segment that is to
224
 
                                be used to service next IO request. */
225
 
        ulint           n_reserved;
226
 
                                /*!< Number of reserved slots in the
227
 
                                aio array outside the ibuf segment */
228
 
        os_aio_slot_t*  slots;  /*!< Pointer to the slots in the array */
 
116
        os_mutex_t      mutex;    /* the mutex protecting the aio array */
 
117
        os_event_t      not_full; /* The event which is set to the signaled
 
118
                                  state when there is space in the aio
 
119
                                  outside the ibuf segment */
 
120
        os_event_t      is_empty; /* The event which is set to the signaled
 
121
                                  state when there are no pending i/os
 
122
                                  in this array */
 
123
        ulint           n_slots;  /* Total number of slots in the aio array.
 
124
                                  This must be divisible by n_threads. */
 
125
        ulint           n_segments;/* Number of segments in the aio array of
 
126
                                  pending aio requests. A thread can wait
 
127
                                  separately for any one of the segments. */
 
128
        ulint           n_reserved;/* Number of reserved slots in the
 
129
                                  aio array outside the ibuf segment */
 
130
        os_aio_slot_t*  slots;    /* Pointer to the slots in the array */
229
131
#ifdef __WIN__
230
 
        HANDLE*         handles;
231
 
                                /*!< Pointer to an array of OS native
232
 
                                event handles where we copied the
233
 
                                handles from slots, in the same
234
 
                                order. This can be used in
235
 
                                WaitForMultipleObjects; used only in
236
 
                                Windows */
237
 
#endif
238
 
 
239
 
#if defined(LINUX_NATIVE_AIO)
240
 
        io_context_t*           aio_ctx;
241
 
                                /* completion queue for IO. There is 
242
 
                                one such queue per segment. Each thread
243
 
                                will work on one ctx exclusively. */
244
 
        struct io_event*        aio_events;
245
 
                                /* The array to collect completed IOs.
246
 
                                There is one such event for each
247
 
                                possible pending IO. The size of the
248
 
                                array is equal to n_slots. */
 
132
        os_native_event_t* native_events;
 
133
                                  /* Pointer to an array of OS native event
 
134
                                  handles where we copied the handles from
 
135
                                  slots, in the same order. This can be used
 
136
                                  in WaitForMultipleObjects; used only in
 
137
                                  Windows */
249
138
#endif
250
139
};
251
140
 
252
 
#if defined(LINUX_NATIVE_AIO)
253
 
/** timeout for each io_getevents() call = 500ms. */
254
 
#define OS_AIO_REAP_TIMEOUT     (500000000UL)
255
 
 
256
 
/** time to sleep, in microseconds if io_setup() returns EAGAIN. */
257
 
#define OS_AIO_IO_SETUP_RETRY_SLEEP     (500000UL)
258
 
 
259
 
/** number of attempts before giving up on io_setup(). */
260
 
#define OS_AIO_IO_SETUP_RETRY_ATTEMPTS  5
261
 
#endif
262
 
 
263
 
/** Array of events used in simulated aio */
 
141
/* Array of events used in simulated aio */
264
142
static os_event_t*      os_aio_segment_wait_events      = NULL;
265
143
 
266
 
/** The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These
267
 
are NULL when the module has not yet been initialized. @{ */
268
 
static os_aio_array_t*  os_aio_read_array       = NULL; /*!< Reads */
269
 
static os_aio_array_t*  os_aio_write_array      = NULL; /*!< Writes */
270
 
static os_aio_array_t*  os_aio_ibuf_array       = NULL; /*!< Insert buffer */
271
 
static os_aio_array_t*  os_aio_log_array        = NULL; /*!< Redo log */
272
 
static os_aio_array_t*  os_aio_sync_array       = NULL; /*!< Synchronous I/O */
273
 
/* @} */
 
144
/* The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These
 
145
are NULL when the module has not yet been initialized. */
 
146
static os_aio_array_t*  os_aio_read_array       = NULL;
 
147
static os_aio_array_t*  os_aio_write_array      = NULL;
 
148
static os_aio_array_t*  os_aio_ibuf_array       = NULL;
 
149
static os_aio_array_t*  os_aio_log_array        = NULL;
 
150
static os_aio_array_t*  os_aio_sync_array       = NULL;
274
151
 
275
 
/** Number of asynchronous I/O segments.  Set by os_aio_init(). */
276
152
static ulint    os_aio_n_segments       = ULINT_UNDEFINED;
277
153
 
278
 
/** If the following is TRUE, read i/o handler threads try to
 
154
/* If the following is TRUE, read i/o handler threads try to
279
155
wait until a batch of new read requests have been posted */
280
156
static ibool    os_aio_recommend_sleep_for_read_threads = FALSE;
281
 
#endif /* !UNIV_HOTBACKUP */
282
157
 
283
158
UNIV_INTERN ulint       os_n_file_reads         = 0;
284
159
UNIV_INTERN ulint       os_bytes_read_since_printout = 0;
291
166
 
292
167
UNIV_INTERN ibool       os_has_said_disk_full   = FALSE;
293
168
 
294
 
#ifndef UNIV_HOTBACKUP
295
 
/** The mutex protecting the following counts of pending I/O operations */
 
169
/* The mutex protecting the following counts of pending I/O operations */
296
170
static os_mutex_t       os_file_count_mutex;
297
 
#endif /* !UNIV_HOTBACKUP */
298
 
/** Number of pending os_file_pread() operations */
299
171
UNIV_INTERN ulint       os_file_n_pending_preads  = 0;
300
 
/** Number of pending os_file_pwrite() operations */
301
172
UNIV_INTERN ulint       os_file_n_pending_pwrites = 0;
302
 
/** Number of pending write operations */
303
173
UNIV_INTERN ulint       os_n_pending_writes = 0;
304
 
/** Number of pending read operations */
305
174
UNIV_INTERN ulint       os_n_pending_reads = 0;
306
175
 
307
 
/***********************************************************************//**
308
 
Gets the operating system version. Currently works only on Windows.
309
 
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000, OS_WINXP, OS_WINVISTA,
310
 
OS_WIN7. */
 
176
/***************************************************************************
 
177
Gets the operating system version. Currently works only on Windows. */
311
178
UNIV_INTERN
312
179
ulint
313
180
os_get_os_version(void)
314
181
/*===================*/
 
182
                  /* out: OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */
315
183
{
316
184
#ifdef __WIN__
317
185
        OSVERSIONINFO     os_info;
325
193
        } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
326
194
                return(OS_WIN95);
327
195
        } 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;
 
196
                if (os_info.dwMajorVersion <= 4) {
 
197
                        return(OS_WINNT);
 
198
                } else {
 
199
                        return(OS_WIN2000);
340
200
                }
341
201
        } else {
342
202
                ut_error;
349
209
#endif
350
210
}
351
211
 
352
 
/***********************************************************************//**
 
212
/***************************************************************************
353
213
Retrieves the last error number if an error occurs in a file io function.
354
214
The number should be retrieved before any other OS calls (because they may
355
215
overwrite the error number). If the number is not known to this program,
356
 
the OS error number + 100 is returned.
357
 
@return error number, or OS error number + 100 */
 
216
the OS error number + 100 is returned. */
358
217
UNIV_INTERN
359
218
ulint
360
219
os_file_get_last_error(
361
220
/*===================*/
362
 
        ibool   report_all_errors)      /*!< in: TRUE if we want an error message
 
221
                                        /* out: error number, or OS error
 
222
                                        number + 100 */
 
223
        ibool   report_all_errors)      /* in: TRUE if we want an error message
363
224
                                        printed of all errors */
364
225
{
365
226
        ulint   err;
404
265
                                " software or another instance\n"
405
266
                                "InnoDB: of MySQL."
406
267
                                " Please close it to get rid of this error.\n");
407
 
                } else if (err == ERROR_WORKING_SET_QUOTA
408
 
                           || err == ERROR_NO_SYSTEM_RESOURCES) {
409
 
                        fprintf(stderr,
410
 
                                "InnoDB: The error means that there are no"
411
 
                                " sufficient system resources or quota to"
412
 
                                " complete the operation.\n");
413
 
                } else if (err == ERROR_OPERATION_ABORTED) {
414
 
                        fprintf(stderr,
415
 
                                "InnoDB: The error means that the I/O"
416
 
                                " operation has been aborted\n"
417
 
                                "InnoDB: because of either a thread exit"
418
 
                                " or an application request.\n"
419
 
                                "InnoDB: Retry attempt is made.\n");
420
268
                } else {
421
269
                        fprintf(stderr,
422
270
                                "InnoDB: Some operating system error numbers"
423
271
                                " are described at\n"
424
272
                                "InnoDB: "
425
 
                                REFMAN
 
273
                                "http://dev.mysql.com/doc/refman/5.1/en/"
426
274
                                "operating-system-error-codes.html\n");
427
275
                }
428
276
        }
438
286
        } else if (err == ERROR_SHARING_VIOLATION
439
287
                   || err == ERROR_LOCK_VIOLATION) {
440
288
                return(OS_FILE_SHARING_VIOLATION);
441
 
        } else if (err == ERROR_WORKING_SET_QUOTA
442
 
                   || err == ERROR_NO_SYSTEM_RESOURCES) {
443
 
                return(OS_FILE_INSUFFICIENT_RESOURCE);
444
 
        } else if (err == ERROR_OPERATION_ABORTED) {
445
 
                return(OS_FILE_OPERATION_ABORTED);
446
289
        } else {
447
290
                return(100 + err);
448
291
        }
486
329
                                "InnoDB: Some operating system"
487
330
                                " error numbers are described at\n"
488
331
                                "InnoDB: "
489
 
                                REFMAN
 
332
                                "http://dev.mysql.com/doc/refman/5.1/en/"
490
333
                                "operating-system-error-codes.html\n");
491
334
                }
492
335
        }
493
336
 
494
337
        fflush(stderr);
495
338
 
496
 
        switch (err) {
497
 
        case ENOSPC:
 
339
        if (err == ENOSPC) {
498
340
                return(OS_FILE_DISK_FULL);
499
 
        case ENOENT:
 
341
        } else if (err == ENOENT) {
500
342
                return(OS_FILE_NOT_FOUND);
501
 
        case EEXIST:
 
343
        } else if (err == EEXIST) {
502
344
                return(OS_FILE_ALREADY_EXISTS);
503
 
        case EXDEV:
504
 
        case ENOTDIR:
505
 
        case EISDIR:
 
345
        } else if (err == EXDEV || err == ENOTDIR || err == EISDIR) {
506
346
                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;
 
347
        } else {
 
348
                return(100 + err);
517
349
        }
518
 
        return(100 + err);
519
350
#endif
520
351
}
521
352
 
522
 
/****************************************************************//**
 
353
/********************************************************************
523
354
Does error handling when a file operation fails.
524
355
Conditionally exits (calling exit(3)) based on should_exit value and the
525
 
error type
526
 
@return TRUE if we should retry the operation */
 
356
error type */
527
357
static
528
358
ibool
529
359
os_file_handle_error_cond_exit(
530
360
/*===========================*/
531
 
        const char*     name,           /*!< in: name of a file or NULL */
532
 
        const char*     operation,      /*!< in: operation */
533
 
        ibool           should_exit)    /*!< in: call exit(3) if unknown error
 
361
                                        /* out: TRUE if we should retry the
 
362
                                        operation */
 
363
        const char*     name,           /* in: name of a file or NULL */
 
364
        const char*     operation,      /* in: operation */
 
365
        ibool           should_exit)    /* in: call exit(3) if unknown error
534
366
                                        and this parameter is TRUE */
535
367
{
536
368
        ulint   err;
565
397
        } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
566
398
 
567
399
                return(TRUE);
568
 
        } else if (err == OS_FILE_AIO_INTERRUPTED) {
569
 
 
570
 
                return(TRUE);
571
400
        } else if (err == OS_FILE_ALREADY_EXISTS
572
401
                   || err == OS_FILE_PATH_ERROR) {
573
402
 
576
405
 
577
406
                os_thread_sleep(10000000);  /* 10 sec */
578
407
                return(TRUE);
579
 
        } else if (err == OS_FILE_INSUFFICIENT_RESOURCE) {
580
 
 
581
 
                os_thread_sleep(100000);        /* 100 ms */
582
 
                return(TRUE);
583
 
        } else if (err == OS_FILE_OPERATION_ABORTED) {
584
 
 
585
 
                os_thread_sleep(100000);        /* 100 ms */
586
 
                return(TRUE);
587
408
        } else {
588
409
                if (name) {
589
410
                        fprintf(stderr, "InnoDB: File name %s\n", name);
604
425
        return(FALSE);
605
426
}
606
427
 
607
 
/****************************************************************//**
608
 
Does error handling when a file operation fails.
609
 
@return TRUE if we should retry the operation */
 
428
/********************************************************************
 
429
Does error handling when a file operation fails. */
610
430
static
611
431
ibool
612
432
os_file_handle_error(
613
433
/*=================*/
614
 
        const char*     name,   /*!< in: name of a file or NULL */
615
 
        const char*     operation)/*!< in: operation */
 
434
                                /* out: TRUE if we should retry the
 
435
                                operation */
 
436
        const char*     name,   /* in: name of a file or NULL */
 
437
        const char*     operation)/* in: operation */
616
438
{
617
439
        /* exit in case of unknown error */
618
440
        return(os_file_handle_error_cond_exit(name, operation, TRUE));
619
441
}
620
442
 
621
 
/****************************************************************//**
622
 
Does error handling when a file operation fails.
623
 
@return TRUE if we should retry the operation */
 
443
/********************************************************************
 
444
Does error handling when a file operation fails. */
624
445
static
625
446
ibool
626
447
os_file_handle_error_no_exit(
627
448
/*=========================*/
628
 
        const char*     name,   /*!< in: name of a file or NULL */
629
 
        const char*     operation)/*!< in: operation */
 
449
                                /* out: TRUE if we should retry the
 
450
                                operation */
 
451
        const char*     name,   /* in: name of a file or NULL */
 
452
        const char*     operation)/* in: operation */
630
453
{
631
454
        /* don't exit in case of unknown error */
632
455
        return(os_file_handle_error_cond_exit(name, operation, FALSE));
634
457
 
635
458
#undef USE_FILE_LOCK
636
459
#define USE_FILE_LOCK
637
 
#if defined(UNIV_HOTBACKUP) || defined(__WIN__)
 
460
#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__NETWARE__)
638
461
/* InnoDB Hot Backup does not lock the data files.
639
462
 * On Windows, mandatory locking is used.
640
463
 */
641
464
# undef USE_FILE_LOCK
642
465
#endif
643
466
#ifdef USE_FILE_LOCK
644
 
/****************************************************************//**
645
 
Obtain an exclusive lock on a file.
646
 
@return 0 on success */
 
467
/********************************************************************
 
468
Obtain an exclusive lock on a file. */
647
469
static
648
470
int
649
471
os_file_lock(
650
472
/*=========*/
651
 
        int             fd,     /*!< in: file descriptor */
652
 
        const char*     name)   /*!< in: file name */
 
473
                                /* out: 0 on success */
 
474
        int             fd,     /* in: file descriptor */
 
475
        const char*     name)   /* in: file name */
653
476
{
654
477
        struct flock lk;
655
478
        lk.l_type = F_WRLCK;
662
485
                if (errno == EAGAIN || errno == EACCES) {
663
486
                        fprintf(stderr,
664
487
                                "InnoDB: Check that you do not already have"
665
 
                                " another drizzled process\n"
 
488
                                " another mysqld process\n"
666
489
                                "InnoDB: using the same InnoDB data"
667
490
                                " or log files.\n");
668
491
                }
674
497
}
675
498
#endif /* USE_FILE_LOCK */
676
499
 
677
 
#ifndef UNIV_HOTBACKUP
678
 
/****************************************************************//**
 
500
/********************************************************************
679
501
Creates the seek mutexes used in positioned reads and writes. */
680
502
UNIV_INTERN
681
503
void
684
506
{
685
507
        ulint   i;
686
508
 
687
 
        os_file_count_mutex = os_mutex_create();
 
509
        os_file_count_mutex = os_mutex_create(NULL);
688
510
 
689
511
        for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
690
 
                os_file_seek_mutexes[i] = os_mutex_create();
 
512
                os_file_seek_mutexes[i] = os_mutex_create(NULL);
691
513
        }
692
514
}
693
515
 
694
 
/***********************************************************************//**
 
516
/***************************************************************************
695
517
Creates a temporary file.  This function is like tmpfile(3), but
696
518
the temporary file is created in the MySQL temporary directory.
697
 
@return temporary file handle, or NULL on error */
 
519
On Netware, this function is like tmpfile(3), because the C run-time
 
520
library of Netware does not expose the delete-on-close flag. */
698
521
UNIV_INTERN
699
522
FILE*
700
523
os_file_create_tmpfile(void)
701
524
/*========================*/
 
525
                        /* out: temporary file handle, or NULL on error */
702
526
{
 
527
#ifdef UNIV_HOTBACKUP
 
528
        ut_error;
 
529
 
 
530
        return(NULL);
 
531
#else
 
532
# ifdef __NETWARE__
 
533
        FILE*   file    = tmpfile();
 
534
# else /* __NETWARE__ */
703
535
        FILE*   file    = NULL;
704
536
        int     fd      = innobase_mysql_tmpfile();
705
537
 
706
538
        if (fd >= 0) {
707
539
                file = fdopen(fd, "w+b");
708
540
        }
 
541
# endif /* __NETWARE__ */
709
542
 
710
543
        if (!file) {
711
544
                ut_print_timestamp(stderr);
712
545
                fprintf(stderr,
713
546
                        "  InnoDB: Error: unable to create temporary file;"
714
547
                        " errno: %d\n", errno);
 
548
# ifndef __NETWARE__
715
549
                if (fd >= 0) {
716
550
                        close(fd);
717
551
                }
 
552
# endif /* !__NETWARE__ */
718
553
        }
719
554
 
720
555
        return(file);
 
556
#endif /* UNIV_HOTBACKUP */
721
557
}
722
 
#endif /* !UNIV_HOTBACKUP */
723
558
 
724
 
/***********************************************************************//**
 
559
/***************************************************************************
725
560
The os_file_opendir() function opens a directory stream corresponding to the
726
561
directory named by the dirname argument. The directory stream is positioned
727
562
at the first entry. In both Unix and Windows we automatically skip the '.'
728
 
and '..' items at the start of the directory listing.
729
 
@return directory stream, NULL if error */
 
563
and '..' items at the start of the directory listing. */
730
564
UNIV_INTERN
731
565
os_file_dir_t
732
566
os_file_opendir(
733
567
/*============*/
734
 
        const char*     dirname,        /*!< in: directory name; it must not
 
568
                                        /* out: directory stream, NULL if
 
569
                                        error */
 
570
        const char*     dirname,        /* in: directory name; it must not
735
571
                                        contain a trailing '\' or '/' */
736
 
        ibool           error_is_fatal) /*!< in: TRUE if we should treat an
 
572
        ibool           error_is_fatal) /* in: TRUE if we should treat an
737
573
                                        error as a fatal error; if we try to
738
574
                                        open symlinks then we do not wish a
739
575
                                        fatal error if it happens not to be
780
616
#endif
781
617
}
782
618
 
783
 
/***********************************************************************//**
784
 
Closes a directory stream.
785
 
@return 0 if success, -1 if failure */
 
619
/***************************************************************************
 
620
Closes a directory stream. */
786
621
UNIV_INTERN
787
622
int
788
623
os_file_closedir(
789
624
/*=============*/
790
 
        os_file_dir_t   dir)    /*!< in: directory stream */
 
625
                                /* out: 0 if success, -1 if failure */
 
626
        os_file_dir_t   dir)    /* in: directory stream */
791
627
{
792
628
#ifdef __WIN__
793
629
        BOOL            ret;
814
650
#endif
815
651
}
816
652
 
817
 
/***********************************************************************//**
 
653
/***************************************************************************
818
654
This function returns information of the next file in the directory. We jump
819
 
over the '.' and '..' entries in the directory.
820
 
@return 0 if ok, -1 if error, 1 if at the end of the directory */
 
655
over the '.' and '..' entries in the directory. */
821
656
UNIV_INTERN
822
657
int
823
658
os_file_readdir_next_file(
824
659
/*======================*/
825
 
        const char*     dirname,/*!< in: directory name or path */
826
 
        os_file_dir_t   dir,    /*!< in: directory stream */
827
 
        os_file_stat_t* info)   /*!< in/out: buffer where the info is returned */
 
660
                                /* out: 0 if ok, -1 if error, 1 if at the end
 
661
                                of the directory */
 
662
        const char*     dirname,/* in: directory name or path */
 
663
        os_file_dir_t   dir,    /* in: directory stream */
 
664
        os_file_stat_t* info)   /* in/out: buffer where the info is returned */
828
665
{
829
666
#ifdef __WIN__
830
667
        LPWIN32_FIND_DATA       lpFindFileData;
856
693
                        /* TODO: MySQL has apparently its own symlink
857
694
                        implementation in Windows, dbname.sym can
858
695
                        redirect a database directory:
859
 
                        REFMAN "windows-symbolic-links.html" */
 
696
                        http://dev.mysql.com/doc/refman/5.1/en/
 
697
                        windows-symbolic-links.html */
860
698
                        info->type = OS_FILE_TYPE_LINK;
861
699
                } else if (lpFindFileData->dwFileAttributes
862
700
                           & FILE_ATTRIBUTE_DIRECTORY) {
900
738
#ifdef HAVE_READDIR_R
901
739
        ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
902
740
 
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
 
           ) {
 
741
        if (ret != 0) {
912
742
                fprintf(stderr,
913
743
                        "InnoDB: cannot read directory %s, error %lu\n",
914
744
                        dirname, (ulong)ret);
940
770
 
941
771
        strcpy(info->name, ent->d_name);
942
772
 
943
 
        full_path = static_cast<char* >(ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10));
 
773
        full_path = ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10);
944
774
 
945
775
        sprintf(full_path, "%s/%s", dirname, ent->d_name);
946
776
 
947
777
        ret = stat(full_path, &statinfo);
948
778
 
949
779
        if (ret) {
950
 
 
951
 
                if (errno == ENOENT) {
952
 
                        /* readdir() returned a file that does not exist,
953
 
                        it must have been deleted in the meantime. Do what
954
 
                        would have happened if the file was deleted before
955
 
                        readdir() - ignore and go to the next entry.
956
 
                        If this is the last entry then info->name will still
957
 
                        contain the name of the deleted file when this
958
 
                        function returns, but this is not an issue since the
959
 
                        caller shouldn't be looking at info when end of
960
 
                        directory is returned. */
961
 
 
962
 
                        ut_free(full_path);
963
 
 
964
 
                        goto next_file;
965
 
                }
966
 
 
967
780
                os_file_handle_error_no_exit(full_path, "stat");
968
781
 
969
782
                ut_free(full_path);
989
802
#endif
990
803
}
991
804
 
992
 
/*****************************************************************//**
 
805
/*********************************************************************
993
806
This function attempts to create a directory named pathname. The new directory
994
807
gets default permissions. On Unix the permissions are (0770 & ~umask). If the
995
808
directory exists already, nothing is done and the call succeeds, unless the
996
 
fail_if_exists arguments is true.
997
 
@return TRUE if call succeeds, FALSE on error */
 
809
fail_if_exists arguments is true. */
998
810
UNIV_INTERN
999
811
ibool
1000
812
os_file_create_directory(
1001
813
/*=====================*/
1002
 
        const char*     pathname,       /*!< in: directory name as
 
814
                                        /* out: TRUE if call succeeds,
 
815
                                        FALSE on error */
 
816
        const char*     pathname,       /* in: directory name as
1003
817
                                        null-terminated string */
1004
 
        ibool           fail_if_exists) /*!< in: if TRUE, pre-existing directory
 
818
        ibool           fail_if_exists) /* in: if TRUE, pre-existing directory
1005
819
                                        is treated as an error. */
1006
820
{
1007
821
#ifdef __WIN__
1034
848
#endif
1035
849
}
1036
850
 
1037
 
/****************************************************************//**
1038
 
NOTE! Use the corresponding macro os_file_create_simple(), not directly
1039
 
this function!
1040
 
A simple function to open or create a file.
1041
 
@return own: handle to the file, not defined if error, error number
1042
 
can be retrieved with os_file_get_last_error */
 
851
/********************************************************************
 
852
A simple function to open or create a file. */
1043
853
UNIV_INTERN
1044
854
os_file_t
1045
 
os_file_create_simple_func(
1046
 
/*=======================*/
1047
 
        const char*     name,   /*!< in: name of the file or path as a
 
855
os_file_create_simple(
 
856
/*==================*/
 
857
                                /* out, own: handle to the file, not defined
 
858
                                if error, error number can be retrieved with
 
859
                                os_file_get_last_error */
 
860
        const char*     name,   /* in: name of the file or path as a
1048
861
                                null-terminated string */
1049
 
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file is
 
862
        ulint           create_mode,/* in: OS_FILE_OPEN if an existing file is
1050
863
                                opened (if does not exist, error), or
1051
864
                                OS_FILE_CREATE if a new file is created
1052
865
                                (if exists, error), or
1053
866
                                OS_FILE_CREATE_PATH if new file
1054
867
                                (if exists, error) and subdirectories along
1055
868
                                its path are created (if needed)*/
1056
 
        ulint           access_type,/*!< in: OS_FILE_READ_ONLY or
 
869
        ulint           access_type,/* in: OS_FILE_READ_ONLY or
1057
870
                                OS_FILE_READ_WRITE */
1058
 
        ibool*          success)/*!< out: TRUE if succeed, FALSE if error */
 
871
        ibool*          success)/* out: TRUE if succeed, FALSE if error */
1059
872
{
1060
873
#ifdef __WIN__
1061
874
        os_file_t       file;
1101
914
                          NULL, /* default security attributes */
1102
915
                          create_flag,
1103
916
                          attributes,
1104
 
                          NULL);        /*!< no template file */
 
917
                          NULL);        /* no template file */
1105
918
 
1106
919
        if (file == INVALID_HANDLE_VALUE) {
1107
920
                *success = FALSE;
1177
990
#endif /* __WIN__ */
1178
991
}
1179
992
 
1180
 
/****************************************************************//**
1181
 
NOTE! Use the corresponding macro
1182
 
os_file_create_simple_no_error_handling(), not directly this function!
1183
 
A simple function to open or create a file.
1184
 
@return own: handle to the file, not defined if error, error number
1185
 
can be retrieved with os_file_get_last_error */
 
993
/********************************************************************
 
994
A simple function to open or create a file. */
1186
995
UNIV_INTERN
1187
996
os_file_t
1188
 
os_file_create_simple_no_error_handling_func(
1189
 
/*=========================================*/
1190
 
        const char*     name,   /*!< in: name of the file or path as a
 
997
os_file_create_simple_no_error_handling(
 
998
/*====================================*/
 
999
                                /* out, own: handle to the file, not defined
 
1000
                                if error, error number can be retrieved with
 
1001
                                os_file_get_last_error */
 
1002
        const char*     name,   /* in: name of the file or path as a
1191
1003
                                null-terminated string */
1192
 
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
 
1004
        ulint           create_mode,/* in: OS_FILE_OPEN if an existing file
1193
1005
                                is opened (if does not exist, error), or
1194
1006
                                OS_FILE_CREATE if a new file is created
1195
1007
                                (if exists, error) */
1196
 
        ulint           access_type,/*!< in: OS_FILE_READ_ONLY,
 
1008
        ulint           access_type,/* in: OS_FILE_READ_ONLY,
1197
1009
                                OS_FILE_READ_WRITE, or
1198
1010
                                OS_FILE_READ_ALLOW_DELETE; the last option is
1199
1011
                                used by a backup program reading the file */
1200
 
        ibool*          success)/*!< out: TRUE if succeed, FALSE if error */
 
1012
        ibool*          success)/* out: TRUE if succeed, FALSE if error */
1201
1013
{
1202
1014
#ifdef __WIN__
1203
1015
        os_file_t       file;
1224
1036
        } else if (access_type == OS_FILE_READ_ALLOW_DELETE) {
1225
1037
                access = GENERIC_READ;
1226
1038
                share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ
1227
 
                        | FILE_SHARE_WRITE;     /*!< A backup program has to give
 
1039
                        | FILE_SHARE_WRITE;     /* A backup program has to give
1228
1040
                                                mysqld the maximum freedom to
1229
1041
                                                do what it likes with the
1230
1042
                                                file */
1239
1051
                          NULL, /* default security attributes */
1240
1052
                          create_flag,
1241
1053
                          attributes,
1242
 
                          NULL);        /*!< no template file */
 
1054
                          NULL);        /* no template file */
1243
1055
 
1244
1056
        if (file == INVALID_HANDLE_VALUE) {
1245
1057
                *success = FALSE;
1291
1103
#endif /* __WIN__ */
1292
1104
}
1293
1105
 
1294
 
/****************************************************************//**
 
1106
/********************************************************************
1295
1107
Tries to disable OS caching on an opened file descriptor. */
1296
1108
UNIV_INTERN
1297
1109
void
1298
1110
os_file_set_nocache(
1299
1111
/*================*/
1300
 
        int             fd,             /*!< in: file descriptor to alter */
1301
 
        const char*     file_name,      /*!< in: used in the diagnostic message */
1302
 
        const char*     operation_name)
1303
 
                                        /*!< in: "open" or "create"; used in the
 
1112
        int             fd,             /* in: file descriptor to alter */
 
1113
        const char*     file_name,      /* in: file name, used in the
 
1114
                                        diagnostic message */
 
1115
        const char*     operation_name) /* in: "open" or "create"; used in the
1304
1116
                                        diagnostic message */
1305
1117
{
1306
1118
        /* some versions of Solaris may not have DIRECTIO_ON */
1338
1150
#endif
1339
1151
}
1340
1152
 
1341
 
/****************************************************************//**
1342
 
NOTE! Use the corresponding macro os_file_create(), not directly
1343
 
this function!
1344
 
Opens an existing file or creates a new.
1345
 
@return own: handle to the file, not defined if error, error number
1346
 
can be retrieved with os_file_get_last_error */
 
1153
/********************************************************************
 
1154
Opens an existing file or creates a new. */
1347
1155
UNIV_INTERN
1348
1156
os_file_t
1349
 
os_file_create_func(
1350
 
/*================*/
1351
 
        const char*     name,   /*!< in: name of the file or path as a
 
1157
os_file_create(
 
1158
/*===========*/
 
1159
                                /* out, own: handle to the file, not defined
 
1160
                                if error, error number can be retrieved with
 
1161
                                os_file_get_last_error */
 
1162
        const char*     name,   /* in: name of the file or path as a
1352
1163
                                null-terminated string */
1353
 
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
 
1164
        ulint           create_mode,/* in: OS_FILE_OPEN if an existing file
1354
1165
                                is opened (if does not exist, error), or
1355
1166
                                OS_FILE_CREATE if a new file is created
1356
1167
                                (if exists, error),
1358
1169
                                or an old overwritten;
1359
1170
                                OS_FILE_OPEN_RAW, if a raw device or disk
1360
1171
                                partition should be opened */
1361
 
        ulint           purpose,/*!< in: OS_FILE_AIO, if asynchronous,
 
1172
        ulint           purpose,/* in: OS_FILE_AIO, if asynchronous,
1362
1173
                                non-buffered i/o is desired,
1363
1174
                                OS_FILE_NORMAL, if any normal file;
1364
1175
                                NOTE that it also depends on type, os_aio_..
1365
1176
                                and srv_.. variables whether we really use
1366
1177
                                async i/o or unbuffered i/o: look in the
1367
1178
                                function source code for the exact rules */
1368
 
        ulint           type,   /*!< in: OS_DATA_FILE or OS_LOG_FILE */
1369
 
        ibool*          success)/*!< out: TRUE if succeed, FALSE if error */
 
1179
        ulint           type,   /* in: OS_DATA_FILE or OS_LOG_FILE */
 
1180
        ibool*          success)/* out: TRUE if succeed, FALSE if error */
1370
1181
{
1371
1182
#ifdef __WIN__
1372
1183
        os_file_t       file;
1397
1208
                buffering of writes in the OS */
1398
1209
                attributes = 0;
1399
1210
#ifdef WIN_ASYNC_IO
1400
 
                if (srv_use_native_aio) {
 
1211
                if (os_aio_use_native_aio) {
1401
1212
                        attributes = attributes | FILE_FLAG_OVERLAPPED;
1402
1213
                }
1403
1214
#endif
1404
1215
#ifdef UNIV_NON_BUFFERED_IO
1405
 
# ifndef UNIV_HOTBACKUP
1406
1216
                if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
1407
1217
                        /* Do not use unbuffered i/o to log files because
1408
1218
                        value 2 denotes that we do not flush the log at every
1411
1221
                           == SRV_WIN_IO_UNBUFFERED) {
1412
1222
                        attributes = attributes | FILE_FLAG_NO_BUFFERING;
1413
1223
                }
1414
 
# else /* !UNIV_HOTBACKUP */
1415
 
                attributes = attributes | FILE_FLAG_NO_BUFFERING;
1416
 
# endif /* !UNIV_HOTBACKUP */
1417
 
#endif /* UNIV_NON_BUFFERED_IO */
 
1224
#endif
1418
1225
        } else if (purpose == OS_FILE_NORMAL) {
1419
1226
                attributes = 0;
1420
1227
#ifdef UNIV_NON_BUFFERED_IO
1421
 
# ifndef UNIV_HOTBACKUP
1422
1228
                if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
1423
1229
                        /* Do not use unbuffered i/o to log files because
1424
1230
                        value 2 denotes that we do not flush the log at every
1427
1233
                           == SRV_WIN_IO_UNBUFFERED) {
1428
1234
                        attributes = attributes | FILE_FLAG_NO_BUFFERING;
1429
1235
                }
1430
 
# else /* !UNIV_HOTBACKUP */
1431
 
                attributes = attributes | FILE_FLAG_NO_BUFFERING;
1432
 
# endif /* !UNIV_HOTBACKUP */
1433
 
#endif /* UNIV_NON_BUFFERED_IO */
 
1236
#endif
1434
1237
        } else {
1435
1238
                attributes = 0;
1436
1239
                ut_error;
1453
1256
                          NULL, /* default security attributes */
1454
1257
                          create_flag,
1455
1258
                          attributes,
1456
 
                          NULL);        /*!< no template file */
 
1259
                          NULL);        /* no template file */
1457
1260
 
1458
1261
        if (file == INVALID_HANDLE_VALUE) {
1459
1262
                *success = FALSE;
1460
1263
 
1461
1264
                /* When srv_file_per_table is on, file creation failure may not
1462
1265
                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 */
 
1266
                case of unknown errors. */
1468
1267
                if (srv_file_per_table) {
1469
1268
                        retry = os_file_handle_error_no_exit(name,
1470
1269
                                                create_mode == OS_FILE_CREATE ?
1488
1287
        int             create_flag;
1489
1288
        ibool           retry;
1490
1289
        const char*     mode_str        = NULL;
 
1290
        const char*     type_str        = NULL;
 
1291
        const char*     purpose_str     = NULL;
1491
1292
 
1492
1293
try_again:
1493
1294
        ut_a(name);
1507
1308
                ut_error;
1508
1309
        }
1509
1310
 
1510
 
        ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE);
1511
 
        ut_a(purpose == OS_FILE_AIO || purpose == OS_FILE_NORMAL);
1512
 
 
 
1311
        if (type == OS_LOG_FILE) {
 
1312
                type_str = "LOG";
 
1313
        } else if (type == OS_DATA_FILE) {
 
1314
                type_str = "DATA";
 
1315
        } else {
 
1316
                ut_error;
 
1317
        }
 
1318
 
 
1319
        if (purpose == OS_FILE_AIO) {
 
1320
                purpose_str = "AIO";
 
1321
        } else if (purpose == OS_FILE_NORMAL) {
 
1322
                purpose_str = "NORMAL";
 
1323
        } else {
 
1324
                ut_error;
 
1325
        }
 
1326
 
 
1327
#if 0
 
1328
        fprintf(stderr, "Opening file %s, mode %s, type %s, purpose %s\n",
 
1329
                name, mode_str, type_str, purpose_str);
 
1330
#endif
1513
1331
#ifdef O_SYNC
1514
1332
        /* We let O_SYNC only affect log files; note that we map O_DSYNC to
1515
1333
        O_SYNC because the datasync options seemed to corrupt files in 2001
1532
1350
 
1533
1351
                /* When srv_file_per_table is on, file creation failure may not
1534
1352
                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 */
 
1353
                case of unknown errors. */
1540
1354
                if (srv_file_per_table) {
1541
1355
                        retry = os_file_handle_error_no_exit(name,
1542
1356
                                                create_mode == OS_FILE_CREATE ?
1595
1409
#endif /* __WIN__ */
1596
1410
}
1597
1411
 
1598
 
/***********************************************************************//**
1599
 
Deletes a file if it exists. The file has to be closed before calling this.
1600
 
@return TRUE if success */
 
1412
/***************************************************************************
 
1413
Deletes a file if it exists. The file has to be closed before calling this. */
1601
1414
UNIV_INTERN
1602
1415
ibool
1603
1416
os_file_delete_if_exists(
1604
1417
/*=====================*/
1605
 
        const char*     name)   /*!< in: file path as a null-terminated string */
 
1418
                                /* out: TRUE if success */
 
1419
        const char*     name)   /* in: file path as a null-terminated string */
1606
1420
{
1607
1421
#ifdef __WIN__
1608
1422
        BOOL    ret;
1657
1471
#endif
1658
1472
}
1659
1473
 
1660
 
/***********************************************************************//**
1661
 
Deletes a file. The file has to be closed before calling this.
1662
 
@return TRUE if success */
 
1474
/***************************************************************************
 
1475
Deletes a file. The file has to be closed before calling this. */
1663
1476
UNIV_INTERN
1664
1477
ibool
1665
1478
os_file_delete(
1666
1479
/*===========*/
1667
 
        const char*     name)   /*!< in: file path as a null-terminated string */
 
1480
                                /* out: TRUE if success */
 
1481
        const char*     name)   /* in: file path as a null-terminated string */
1668
1482
{
1669
1483
#ifdef __WIN__
1670
1484
        BOOL    ret;
1720
1534
#endif
1721
1535
}
1722
1536
 
1723
 
/***********************************************************************//**
1724
 
NOTE! Use the corresponding macro os_file_rename(), not directly this function!
 
1537
/***************************************************************************
1725
1538
Renames a file (can also move it to another directory). It is safest that the
1726
 
file is closed before calling this function.
1727
 
@return TRUE if success */
 
1539
file is closed before calling this function. */
1728
1540
UNIV_INTERN
1729
1541
ibool
1730
 
os_file_rename_func(
1731
 
/*================*/
1732
 
        const char*     oldpath,/*!< in: old file path as a null-terminated
 
1542
os_file_rename(
 
1543
/*===========*/
 
1544
                                /* out: TRUE if success */
 
1545
        const char*     oldpath,/* in: old file path as a null-terminated
1733
1546
                                string */
1734
 
        const char*     newpath)/*!< in: new file path */
 
1547
        const char*     newpath)/* in: new file path */
1735
1548
{
1736
1549
#ifdef __WIN__
1737
1550
        BOOL    ret;
1760
1573
#endif
1761
1574
}
1762
1575
 
1763
 
/***********************************************************************//**
1764
 
NOTE! Use the corresponding macro os_file_close(), not directly this function!
 
1576
/***************************************************************************
1765
1577
Closes a file handle. In case of error, error number can be retrieved with
1766
 
os_file_get_last_error.
1767
 
@return TRUE if success */
 
1578
os_file_get_last_error. */
1768
1579
UNIV_INTERN
1769
1580
ibool
1770
 
os_file_close_func(
1771
 
/*===============*/
1772
 
        os_file_t       file)   /*!< in, own: handle to a file */
 
1581
os_file_close(
 
1582
/*==========*/
 
1583
                                /* out: TRUE if success */
 
1584
        os_file_t       file)   /* in, own: handle to a file */
1773
1585
{
1774
1586
#ifdef __WIN__
1775
1587
        BOOL    ret;
1800
1612
#endif
1801
1613
}
1802
1614
 
1803
 
#ifdef UNIV_HOTBACKUP
1804
 
/***********************************************************************//**
1805
 
Closes a file handle.
1806
 
@return TRUE if success */
 
1615
/***************************************************************************
 
1616
Closes a file handle. */
1807
1617
UNIV_INTERN
1808
1618
ibool
1809
1619
os_file_close_no_error_handling(
1810
1620
/*============================*/
1811
 
        os_file_t       file)   /*!< in, own: handle to a file */
 
1621
                                /* out: TRUE if success */
 
1622
        os_file_t       file)   /* in, own: handle to a file */
1812
1623
{
1813
1624
#ifdef __WIN__
1814
1625
        BOOL    ret;
1835
1646
        return(TRUE);
1836
1647
#endif
1837
1648
}
1838
 
#endif /* UNIV_HOTBACKUP */
1839
1649
 
1840
 
/***********************************************************************//**
1841
 
Gets a file size.
1842
 
@return TRUE if success */
 
1650
/***************************************************************************
 
1651
Gets a file size. */
1843
1652
UNIV_INTERN
1844
1653
ibool
1845
1654
os_file_get_size(
1846
1655
/*=============*/
1847
 
        os_file_t       file,   /*!< in: handle to a file */
1848
 
        ulint*          size,   /*!< out: least significant 32 bits of file
 
1656
                                /* out: TRUE if success */
 
1657
        os_file_t       file,   /* in: handle to a file */
 
1658
        ulint*          size,   /* out: least significant 32 bits of file
1849
1659
                                size */
1850
 
        ulint*          size_high)/*!< out: most significant 32 bits of size */
 
1660
        ulint*          size_high)/* out: most significant 32 bits of size */
1851
1661
{
1852
1662
#ifdef __WIN__
1853
1663
        DWORD   high;
1885
1695
#endif
1886
1696
}
1887
1697
 
1888
 
/***********************************************************************//**
1889
 
Gets file size as a 64-bit integer ib_int64_t.
1890
 
@return size in bytes, -1 if error */
 
1698
/***************************************************************************
 
1699
Gets file size as a 64-bit integer ib_int64_t. */
1891
1700
UNIV_INTERN
1892
1701
ib_int64_t
1893
1702
os_file_get_size_as_iblonglong(
1894
1703
/*===========================*/
1895
 
        os_file_t       file)   /*!< in: handle to a file */
 
1704
                                /* out: size in bytes, -1 if error */
 
1705
        os_file_t       file)   /* in: handle to a file */
1896
1706
{
1897
1707
        ulint   size;
1898
1708
        ulint   size_high;
1908
1718
        return((((ib_int64_t)size_high) << 32) + (ib_int64_t)size);
1909
1719
}
1910
1720
 
1911
 
/***********************************************************************//**
1912
 
Write the specified number of zeros to a newly created file.
1913
 
@return TRUE if success */
 
1721
/***************************************************************************
 
1722
Write the specified number of zeros to a newly created file. */
1914
1723
UNIV_INTERN
1915
1724
ibool
1916
1725
os_file_set_size(
1917
1726
/*=============*/
1918
 
        const char*     name,   /*!< in: name of the file or path as a
 
1727
                                /* out: TRUE if success */
 
1728
        const char*     name,   /* in: name of the file or path as a
1919
1729
                                null-terminated string */
1920
 
        os_file_t       file,   /*!< in: handle to a file */
1921
 
        ulint           size,   /*!< in: least significant 32 bits of file
 
1730
        os_file_t       file,   /* in: handle to a file */
 
1731
        ulint           size,   /* in: least significant 32 bits of file
1922
1732
                                size */
1923
 
        ulint           size_high)/*!< in: most significant 32 bits of size */
 
1733
        ulint           size_high)/* in: most significant 32 bits of size */
1924
1734
{
1925
1735
        ib_int64_t      current_size;
1926
1736
        ib_int64_t      desired_size;
1937
1747
        /* Write up to 1 megabyte at a time. */
1938
1748
        buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE))
1939
1749
                * UNIV_PAGE_SIZE;
1940
 
        buf2 = static_cast<unsigned char *>(ut_malloc(buf_size + UNIV_PAGE_SIZE));
 
1750
        buf2 = ut_malloc(buf_size + UNIV_PAGE_SIZE);
1941
1751
 
1942
1752
        /* Align the buffer for possible raw i/o */
1943
 
        buf = static_cast<unsigned char *>(ut_align(buf2, UNIV_PAGE_SIZE));
 
1753
        buf = ut_align(buf2, UNIV_PAGE_SIZE);
1944
1754
 
1945
1755
        /* Write buffer full of zeros */
1946
1756
        memset(buf, 0, buf_size);
1997
1807
        return(FALSE);
1998
1808
}
1999
1809
 
2000
 
/***********************************************************************//**
2001
 
Truncates a file at its current position.
2002
 
@return TRUE if success */
 
1810
/***************************************************************************
 
1811
Truncates a file at its current position. */
2003
1812
UNIV_INTERN
2004
1813
ibool
2005
1814
os_file_set_eof(
2006
1815
/*============*/
2007
 
        FILE*           file)   /*!< in: file to be truncated */
 
1816
                                /* out: TRUE if success */
 
1817
        FILE*           file)   /* in: file to be truncated */
2008
1818
{
2009
1819
#ifdef __WIN__
2010
1820
        HANDLE h = (HANDLE) _get_osfhandle(fileno(file));
2015
1825
}
2016
1826
 
2017
1827
#ifndef __WIN__
2018
 
/***********************************************************************//**
 
1828
/***************************************************************************
2019
1829
Wrapper to fsync(2) that retries the call on some errors.
2020
1830
Returns the value 0 if successful; otherwise the value -1 is returned and
2021
 
the global variable errno is set to indicate the error.
2022
 
@return 0 if success, -1 otherwise */
 
1831
the global variable errno is set to indicate the error. */
2023
1832
 
2024
1833
static
2025
1834
int
2026
1835
os_file_fsync(
2027
1836
/*==========*/
2028
 
        os_file_t       file)   /*!< in: handle to a file */
 
1837
                                /* out: 0 if success, -1 otherwise */
 
1838
        os_file_t       file)   /* in: handle to a file */
2029
1839
{
2030
1840
        int     ret;
2031
1841
        int     failures;
2063
1873
}
2064
1874
#endif /* !__WIN__ */
2065
1875
 
2066
 
/***********************************************************************//**
2067
 
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
2068
 
Flushes the write buffers of a given file to the disk.
2069
 
@return TRUE if success */
 
1876
/***************************************************************************
 
1877
Flushes the write buffers of a given file to the disk. */
2070
1878
UNIV_INTERN
2071
1879
ibool
2072
 
os_file_flush_func(
2073
 
/*===============*/
2074
 
        os_file_t       file)   /*!< in, own: handle to a file */
 
1880
os_file_flush(
 
1881
/*==========*/
 
1882
                                /* out: TRUE if success */
 
1883
        os_file_t       file)   /* in, own: handle to a file */
2075
1884
{
2076
1885
#ifdef __WIN__
2077
1886
        BOOL    ret;
2163
1972
}
2164
1973
 
2165
1974
#ifndef __WIN__
2166
 
/*******************************************************************//**
2167
 
Does a synchronous read operation in Posix.
2168
 
@return number of bytes read, -1 if error */
 
1975
/***********************************************************************
 
1976
Does a synchronous read operation in Posix. */
2169
1977
static
2170
1978
ssize_t
2171
1979
os_file_pread(
2172
1980
/*==========*/
2173
 
        os_file_t       file,   /*!< in: handle to a file */
2174
 
        void*           buf,    /*!< in: buffer where to read */
2175
 
        ulint           n,      /*!< in: number of bytes to read */
2176
 
        ulint           offset, /*!< in: least significant 32 bits of file
 
1981
                                /* out: number of bytes read, -1 if error */
 
1982
        os_file_t       file,   /* in: handle to a file */
 
1983
        void*           buf,    /* in: buffer where to read */
 
1984
        ulint           n,      /* in: number of bytes to read */
 
1985
        ulint           offset, /* in: least significant 32 bits of file
2177
1986
                                offset from where to read */
2178
 
        ulint           offset_high) /*!< in: most significant 32 bits of
 
1987
        ulint           offset_high) /* in: most significant 32 bits of
2179
1988
                                offset */
2180
1989
{
2181
1990
        off_t   offs;
2182
 
#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
2183
1991
        ssize_t n_bytes;
2184
 
#endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */
2185
1992
 
2186
1993
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2187
1994
 
2220
2027
        {
2221
2028
                off_t   ret_offset;
2222
2029
                ssize_t ret;
2223
 
#ifndef UNIV_HOTBACKUP
2224
2030
                ulint   i;
2225
 
#endif /* !UNIV_HOTBACKUP */
2226
2031
 
2227
2032
                os_mutex_enter(os_file_count_mutex);
2228
2033
                os_n_pending_reads++;
2229
2034
                os_mutex_exit(os_file_count_mutex);
2230
2035
 
2231
 
#ifndef UNIV_HOTBACKUP
2232
2036
                /* Protect the seek / read operation with a mutex */
2233
2037
                i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2234
2038
 
2235
2039
                os_mutex_enter(os_file_seek_mutexes[i]);
2236
 
#endif /* !UNIV_HOTBACKUP */
2237
2040
 
2238
2041
                ret_offset = lseek(file, offs, SEEK_SET);
2239
2042
 
2243
2046
                        ret = read(file, buf, (ssize_t)n);
2244
2047
                }
2245
2048
 
2246
 
#ifndef UNIV_HOTBACKUP
2247
2049
                os_mutex_exit(os_file_seek_mutexes[i]);
2248
 
#endif /* !UNIV_HOTBACKUP */
2249
2050
 
2250
2051
                os_mutex_enter(os_file_count_mutex);
2251
2052
                os_n_pending_reads--;
2256
2057
#endif
2257
2058
}
2258
2059
 
2259
 
/*******************************************************************//**
2260
 
Does a synchronous write operation in Posix.
2261
 
@return number of bytes written, -1 if error */
 
2060
/***********************************************************************
 
2061
Does a synchronous write operation in Posix. */
2262
2062
static
2263
2063
ssize_t
2264
2064
os_file_pwrite(
2265
2065
/*===========*/
2266
 
        os_file_t       file,   /*!< in: handle to a file */
2267
 
        const void*     buf,    /*!< in: buffer from where to write */
2268
 
        ulint           n,      /*!< in: number of bytes to write */
2269
 
        ulint           offset, /*!< in: least significant 32 bits of file
 
2066
                                /* out: number of bytes written, -1 if error */
 
2067
        os_file_t       file,   /* in: handle to a file */
 
2068
        const void*     buf,    /* in: buffer from where to write */
 
2069
        ulint           n,      /* in: number of bytes to write */
 
2070
        ulint           offset, /* in: least significant 32 bits of file
2270
2071
                                offset where to write */
2271
 
        ulint           offset_high) /*!< in: most significant 32 bits of
 
2072
        ulint           offset_high) /* in: most significant 32 bits of
2272
2073
                                offset */
2273
2074
{
2274
2075
        ssize_t ret;
2323
2124
#else
2324
2125
        {
2325
2126
                off_t   ret_offset;
2326
 
# ifndef UNIV_HOTBACKUP
2327
2127
                ulint   i;
2328
 
# endif /* !UNIV_HOTBACKUP */
2329
2128
 
2330
2129
                os_mutex_enter(os_file_count_mutex);
2331
2130
                os_n_pending_writes++;
2332
2131
                os_mutex_exit(os_file_count_mutex);
2333
2132
 
2334
 
# ifndef UNIV_HOTBACKUP
2335
2133
                /* Protect the seek / write operation with a mutex */
2336
2134
                i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2337
2135
 
2338
2136
                os_mutex_enter(os_file_seek_mutexes[i]);
2339
 
# endif /* UNIV_HOTBACKUP */
2340
2137
 
2341
2138
                ret_offset = lseek(file, offs, SEEK_SET);
2342
2139
 
2362
2159
# endif /* UNIV_DO_FLUSH */
2363
2160
 
2364
2161
func_exit:
2365
 
# ifndef UNIV_HOTBACKUP
2366
2162
                os_mutex_exit(os_file_seek_mutexes[i]);
2367
 
# endif /* !UNIV_HOTBACKUP */
2368
2163
 
2369
2164
                os_mutex_enter(os_file_count_mutex);
2370
2165
                os_n_pending_writes--;
2376
2171
}
2377
2172
#endif
2378
2173
 
2379
 
/*******************************************************************//**
2380
 
NOTE! Use the corresponding macro os_file_read(), not directly this
2381
 
function!
2382
 
Requests a synchronous positioned read operation.
2383
 
@return TRUE if request was successful, FALSE if fail */
 
2174
/***********************************************************************
 
2175
Requests a synchronous positioned read operation. */
2384
2176
UNIV_INTERN
2385
2177
ibool
2386
 
os_file_read_func(
2387
 
/*==============*/
2388
 
        os_file_t       file,   /*!< in: handle to a file */
2389
 
        void*           buf,    /*!< in: buffer where to read */
2390
 
        ulint           offset, /*!< in: least significant 32 bits of file
 
2178
os_file_read(
 
2179
/*=========*/
 
2180
                                /* out: TRUE if request was
 
2181
                                successful, FALSE if fail */
 
2182
        os_file_t       file,   /* in: handle to a file */
 
2183
        void*           buf,    /* in: buffer where to read */
 
2184
        ulint           offset, /* in: least significant 32 bits of file
2391
2185
                                offset where to read */
2392
 
        ulint           offset_high, /*!< in: most significant 32 bits of
 
2186
        ulint           offset_high, /* in: most significant 32 bits of
2393
2187
                                offset */
2394
 
        ulint           n)      /*!< in: number of bytes to read */
 
2188
        ulint           n)      /* in: number of bytes to read */
2395
2189
{
2396
2190
#ifdef __WIN__
2397
2191
        BOOL            ret;
2400
2194
        DWORD           low;
2401
2195
        DWORD           high;
2402
2196
        ibool           retry;
2403
 
#ifndef UNIV_HOTBACKUP
2404
2197
        ulint           i;
2405
 
#endif /* !UNIV_HOTBACKUP */
2406
2198
 
2407
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2408
 
        no more than 32 bits. */
2409
2199
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2410
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2411
2200
 
2412
2201
        os_n_file_reads++;
2413
2202
        os_bytes_read_since_printout += n;
2424
2213
        os_n_pending_reads++;
2425
2214
        os_mutex_exit(os_file_count_mutex);
2426
2215
 
2427
 
#ifndef UNIV_HOTBACKUP
2428
2216
        /* Protect the seek / read operation with a mutex */
2429
2217
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2430
2218
 
2431
2219
        os_mutex_enter(os_file_seek_mutexes[i]);
2432
 
#endif /* !UNIV_HOTBACKUP */
2433
2220
 
2434
2221
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2435
2222
 
2436
2223
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2437
2224
 
2438
 
#ifndef UNIV_HOTBACKUP
2439
2225
                os_mutex_exit(os_file_seek_mutexes[i]);
2440
 
#endif /* !UNIV_HOTBACKUP */
2441
2226
 
2442
2227
                os_mutex_enter(os_file_count_mutex);
2443
2228
                os_n_pending_reads--;
2448
2233
 
2449
2234
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
2450
2235
 
2451
 
#ifndef UNIV_HOTBACKUP
2452
2236
        os_mutex_exit(os_file_seek_mutexes[i]);
2453
 
#endif /* !UNIV_HOTBACKUP */
2454
2237
 
2455
2238
        os_mutex_enter(os_file_count_mutex);
2456
2239
        os_n_pending_reads--;
2459
2242
        if (ret && len == n) {
2460
2243
                return(TRUE);
2461
2244
        }
2462
 
#else /* __WIN__ */
 
2245
#else
2463
2246
        ibool   retry;
2464
2247
        ssize_t ret;
2465
2248
 
2478
2261
                "InnoDB: Was only able to read %ld.\n",
2479
2262
                (ulong)n, (ulong)offset_high,
2480
2263
                (ulong)offset, (long)ret);
2481
 
#endif /* __WIN__ */
 
2264
#endif
2482
2265
#ifdef __WIN__
2483
2266
error_handling:
2484
2267
#endif
2504
2287
        return(FALSE);
2505
2288
}
2506
2289
 
2507
 
/*******************************************************************//**
2508
 
NOTE! Use the corresponding macro os_file_read_no_error_handling(),
2509
 
not directly this function!
 
2290
/***********************************************************************
2510
2291
Requests a synchronous positioned read operation. This function does not do
2511
 
any error handling. In case of error it returns FALSE.
2512
 
@return TRUE if request was successful, FALSE if fail */
 
2292
any error handling. In case of error it returns FALSE. */
2513
2293
UNIV_INTERN
2514
2294
ibool
2515
 
os_file_read_no_error_handling_func(
2516
 
/*================================*/
2517
 
        os_file_t       file,   /*!< in: handle to a file */
2518
 
        void*           buf,    /*!< in: buffer where to read */
2519
 
        ulint           offset, /*!< in: least significant 32 bits of file
 
2295
os_file_read_no_error_handling(
 
2296
/*===========================*/
 
2297
                                /* out: TRUE if request was
 
2298
                                successful, FALSE if fail */
 
2299
        os_file_t       file,   /* in: handle to a file */
 
2300
        void*           buf,    /* in: buffer where to read */
 
2301
        ulint           offset, /* in: least significant 32 bits of file
2520
2302
                                offset where to read */
2521
 
        ulint           offset_high, /*!< in: most significant 32 bits of
 
2303
        ulint           offset_high, /* in: most significant 32 bits of
2522
2304
                                offset */
2523
 
        ulint           n)      /*!< in: number of bytes to read */
 
2305
        ulint           n)      /* in: number of bytes to read */
2524
2306
{
2525
2307
#ifdef __WIN__
2526
2308
        BOOL            ret;
2529
2311
        DWORD           low;
2530
2312
        DWORD           high;
2531
2313
        ibool           retry;
2532
 
#ifndef UNIV_HOTBACKUP
2533
2314
        ulint           i;
2534
 
#endif /* !UNIV_HOTBACKUP */
2535
2315
 
2536
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2537
 
        no more than 32 bits. */
2538
2316
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2539
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2540
2317
 
2541
2318
        os_n_file_reads++;
2542
2319
        os_bytes_read_since_printout += n;
2553
2330
        os_n_pending_reads++;
2554
2331
        os_mutex_exit(os_file_count_mutex);
2555
2332
 
2556
 
#ifndef UNIV_HOTBACKUP
2557
2333
        /* Protect the seek / read operation with a mutex */
2558
2334
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2559
2335
 
2560
2336
        os_mutex_enter(os_file_seek_mutexes[i]);
2561
 
#endif /* !UNIV_HOTBACKUP */
2562
2337
 
2563
2338
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2564
2339
 
2565
2340
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2566
2341
 
2567
 
#ifndef UNIV_HOTBACKUP
2568
2342
                os_mutex_exit(os_file_seek_mutexes[i]);
2569
 
#endif /* !UNIV_HOTBACKUP */
2570
2343
 
2571
2344
                os_mutex_enter(os_file_count_mutex);
2572
2345
                os_n_pending_reads--;
2577
2350
 
2578
2351
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
2579
2352
 
2580
 
#ifndef UNIV_HOTBACKUP
2581
2353
        os_mutex_exit(os_file_seek_mutexes[i]);
2582
 
#endif /* !UNIV_HOTBACKUP */
2583
2354
 
2584
2355
        os_mutex_enter(os_file_count_mutex);
2585
2356
        os_n_pending_reads--;
2588
2359
        if (ret && len == n) {
2589
2360
                return(TRUE);
2590
2361
        }
2591
 
#else /* __WIN__ */
 
2362
#else
2592
2363
        ibool   retry;
2593
2364
        ssize_t ret;
2594
2365
 
2601
2372
 
2602
2373
                return(TRUE);
2603
2374
        }
2604
 
#endif /* __WIN__ */
 
2375
#endif
2605
2376
#ifdef __WIN__
2606
2377
error_handling:
2607
2378
#endif
2614
2385
        return(FALSE);
2615
2386
}
2616
2387
 
2617
 
/*******************************************************************//**
 
2388
/***********************************************************************
2618
2389
Rewind file to its start, read at most size - 1 bytes from it to str, and
2619
2390
NUL-terminate str. All errors are silently ignored. This function is
2620
2391
mostly meant to be used with temporary files. */
2622
2393
void
2623
2394
os_file_read_string(
2624
2395
/*================*/
2625
 
        FILE*   file,   /*!< in: file to read from */
2626
 
        char*   str,    /*!< in: buffer where to read */
2627
 
        ulint   size)   /*!< in: size of buffer */
 
2396
        FILE*   file,   /* in: file to read from */
 
2397
        char*   str,    /* in: buffer where to read */
 
2398
        ulint   size)   /* in: size of buffer */
2628
2399
{
2629
2400
        size_t  flen;
2630
2401
 
2637
2408
        str[flen] = '\0';
2638
2409
}
2639
2410
 
2640
 
/*******************************************************************//**
2641
 
NOTE! Use the corresponding macro os_file_write(), not directly
2642
 
this function!
2643
 
Requests a synchronous write operation.
2644
 
@return TRUE if request was successful, FALSE if fail */
 
2411
/***********************************************************************
 
2412
Requests a synchronous write operation. */
2645
2413
UNIV_INTERN
2646
2414
ibool
2647
 
os_file_write_func(
2648
 
/*===============*/
2649
 
        const char*     name,   /*!< in: name of the file or path as a
 
2415
os_file_write(
 
2416
/*==========*/
 
2417
                                /* out: TRUE if request was
 
2418
                                successful, FALSE if fail */
 
2419
        const char*     name,   /* in: name of the file or path as a
2650
2420
                                null-terminated string */
2651
 
        os_file_t       file,   /*!< in: handle to a file */
2652
 
        const void*     buf,    /*!< in: buffer from which to write */
2653
 
        ulint           offset, /*!< in: least significant 32 bits of file
 
2421
        os_file_t       file,   /* in: handle to a file */
 
2422
        const void*     buf,    /* in: buffer from which to write */
 
2423
        ulint           offset, /* in: least significant 32 bits of file
2654
2424
                                offset where to write */
2655
 
        ulint           offset_high, /*!< in: most significant 32 bits of
 
2425
        ulint           offset_high, /* in: most significant 32 bits of
2656
2426
                                offset */
2657
 
        ulint           n)      /*!< in: number of bytes to write */
 
2427
        ulint           n)      /* in: number of bytes to write */
2658
2428
{
2659
2429
#ifdef __WIN__
2660
2430
        BOOL            ret;
2662
2432
        DWORD           ret2;
2663
2433
        DWORD           low;
2664
2434
        DWORD           high;
 
2435
        ulint           i;
2665
2436
        ulint           n_retries       = 0;
2666
2437
        ulint           err;
2667
 
#ifndef UNIV_HOTBACKUP
2668
 
        ulint           i;
2669
 
#endif /* !UNIV_HOTBACKUP */
2670
2438
 
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);
 
2439
        ut_a((offset & 0xFFFFFFFF) == offset);
2675
2440
 
2676
2441
        os_n_file_writes++;
2677
2442
 
2686
2451
        os_n_pending_writes++;
2687
2452
        os_mutex_exit(os_file_count_mutex);
2688
2453
 
2689
 
#ifndef UNIV_HOTBACKUP
2690
2454
        /* Protect the seek / write operation with a mutex */
2691
2455
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2692
2456
 
2693
2457
        os_mutex_enter(os_file_seek_mutexes[i]);
2694
 
#endif /* !UNIV_HOTBACKUP */
2695
2458
 
2696
2459
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2697
2460
 
2698
2461
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2699
2462
 
2700
 
#ifndef UNIV_HOTBACKUP
2701
2463
                os_mutex_exit(os_file_seek_mutexes[i]);
2702
 
#endif /* !UNIV_HOTBACKUP */
2703
2464
 
2704
2465
                os_mutex_enter(os_file_count_mutex);
2705
2466
                os_n_pending_writes--;
2715
2476
                        "InnoDB: Some operating system error numbers"
2716
2477
                        " are described at\n"
2717
2478
                        "InnoDB: "
2718
 
                        REFMAN "operating-system-error-codes.html\n",
 
2479
                        "http://dev.mysql.com/doc/refman/5.1/en/"
 
2480
                        "operating-system-error-codes.html\n",
2719
2481
                        name, (ulong) offset_high, (ulong) offset,
2720
2482
                        (ulong) GetLastError());
2721
2483
 
2733
2495
        }
2734
2496
# endif /* UNIV_DO_FLUSH */
2735
2497
 
2736
 
#ifndef UNIV_HOTBACKUP
2737
2498
        os_mutex_exit(os_file_seek_mutexes[i]);
2738
 
#endif /* !UNIV_HOTBACKUP */
2739
2499
 
2740
2500
        os_mutex_enter(os_file_count_mutex);
2741
2501
        os_n_pending_writes--;
2788
2548
                        "InnoDB: Some operating system error numbers"
2789
2549
                        " are described at\n"
2790
2550
                        "InnoDB: "
2791
 
                        REFMAN "operating-system-error-codes.html\n");
 
2551
                        "http://dev.mysql.com/doc/refman/5.1/en/"
 
2552
                        "operating-system-error-codes.html\n");
2792
2553
 
2793
2554
                os_has_said_disk_full = TRUE;
2794
2555
        }
2830
2591
                        "InnoDB: Some operating system error numbers"
2831
2592
                        " are described at\n"
2832
2593
                        "InnoDB: "
2833
 
                        REFMAN "operating-system-error-codes.html\n");
 
2594
                        "http://dev.mysql.com/doc/refman/5.1/en/"
 
2595
                        "operating-system-error-codes.html\n");
2834
2596
 
2835
2597
                os_has_said_disk_full = TRUE;
2836
2598
        }
2839
2601
#endif
2840
2602
}
2841
2603
 
2842
 
/*******************************************************************//**
2843
 
Check the existence and type of the given file.
2844
 
@return TRUE if call succeeded */
 
2604
/***********************************************************************
 
2605
Check the existence and type of the given file. */
2845
2606
UNIV_INTERN
2846
2607
ibool
2847
2608
os_file_status(
2848
2609
/*===========*/
2849
 
        const char*     path,   /*!< in:        pathname of the file */
2850
 
        ibool*          exists, /*!< out: TRUE if file exists */
2851
 
        os_file_type_t* type)   /*!< out: type of the file (if it exists) */
 
2610
                                /* out: TRUE if call succeeded */
 
2611
        const char*     path,   /* in:  pathname of the file */
 
2612
        ibool*          exists, /* out: TRUE if file exists */
 
2613
        os_file_type_t* type)   /* out: type of the file (if it exists) */
2852
2614
{
2853
2615
#ifdef __WIN__
2854
2616
        int             ret;
2911
2673
#endif
2912
2674
}
2913
2675
 
2914
 
/*******************************************************************//**
2915
 
This function returns information about the specified file
2916
 
@return TRUE if stat information found */
 
2676
/***********************************************************************
 
2677
This function returns information about the specified file */
2917
2678
UNIV_INTERN
2918
2679
ibool
2919
2680
os_file_get_status(
2920
2681
/*===============*/
2921
 
        const char*     path,           /*!< in:        pathname of the file */
2922
 
        os_file_stat_t* stat_info)      /*!< information of a file in a
 
2682
                                        /* out: TRUE if stat
 
2683
                                        information found */
 
2684
        const char*     path,           /* in:  pathname of the file */
 
2685
        os_file_stat_t* stat_info)      /* information of a file in a
2923
2686
                                        directory */
2924
2687
{
2925
2688
#ifdef __WIN__
2996
2759
#  define OS_FILE_PATH_SEPARATOR        '/'
2997
2760
#endif
2998
2761
 
2999
 
/****************************************************************//**
 
2762
/********************************************************************
3000
2763
The function os_file_dirname returns a directory component of a
3001
2764
null-terminated pathname string.  In the usual case, dirname returns
3002
2765
the string up to, but not including, the final '/', and basename
3022
2785
       "/"            "/"            "/"
3023
2786
       "."            "."            "."
3024
2787
       ".."           "."            ".."
3025
 
 
3026
 
@return own: directory component of the pathname */
 
2788
*/
3027
2789
UNIV_INTERN
3028
2790
char*
3029
2791
os_file_dirname(
3030
2792
/*============*/
3031
 
        const char*     path)   /*!< in: pathname */
 
2793
                                /* out, own: directory component of the
 
2794
                                pathname */
 
2795
        const char*     path)   /* in: pathname */
3032
2796
{
3033
2797
        /* Find the offset of the last slash */
3034
2798
        const char* last_slash = strrchr(path, OS_FILE_PATH_SEPARATOR);
3051
2815
        return(mem_strdupl(path, last_slash - path));
3052
2816
}
3053
2817
 
3054
 
/****************************************************************//**
3055
 
Creates all missing subdirectories along the given path.
3056
 
@return TRUE if call succeeded FALSE otherwise */
 
2818
/********************************************************************
 
2819
Creates all missing subdirectories along the given path. */
3057
2820
UNIV_INTERN
3058
2821
ibool
3059
2822
os_file_create_subdirs_if_needed(
3060
2823
/*=============================*/
3061
 
        const char*     path)   /*!< in: path name */
 
2824
                                /* out: TRUE if call succeeded
 
2825
                                   FALSE otherwise */
 
2826
        const char*     path)   /* in: path name */
3062
2827
{
3063
2828
        char*           subdir;
3064
2829
        ibool           success, subdir_exists;
3091
2856
        return(success);
3092
2857
}
3093
2858
 
3094
 
#ifndef UNIV_HOTBACKUP
3095
 
/****************************************************************//**
3096
 
Returns a pointer to the nth slot in the aio array.
3097
 
@return pointer to slot */
 
2859
/********************************************************************
 
2860
Returns a pointer to the nth slot in the aio array. */
3098
2861
static
3099
2862
os_aio_slot_t*
3100
2863
os_aio_array_get_nth_slot(
3101
2864
/*======================*/
3102
 
        os_aio_array_t*         array,  /*!< in: aio array */
3103
 
        ulint                   index)  /*!< in: index of the slot */
 
2865
                                        /* out: pointer to slot */
 
2866
        os_aio_array_t*         array,  /* in: aio array */
 
2867
        ulint                   index)  /* in: index of the slot */
3104
2868
{
3105
2869
        ut_a(index < array->n_slots);
3106
2870
 
3107
2871
        return((array->slots) + index);
3108
2872
}
3109
2873
 
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 */
 
2874
/****************************************************************************
 
2875
Creates an aio wait array. */
3203
2876
static
3204
2877
os_aio_array_t*
3205
2878
os_aio_array_create(
3206
2879
/*================*/
3207
 
        ulint   n,              /*!< in: maximum number of pending aio
3208
 
                                operations allowed; n must be
3209
 
                                divisible by n_segments */
3210
 
        ulint   n_segments)     /*!< in: number of segments in the aio array */
 
2880
                                /* out, own: aio array */
 
2881
        ulint   n,              /* in: maximum number of pending aio operations
 
2882
                                allowed; n must be divisible by n_segments */
 
2883
        ulint   n_segments)     /* in: number of segments in the aio array */
3211
2884
{
3212
2885
        os_aio_array_t* array;
3213
2886
        ulint           i;
3214
2887
        os_aio_slot_t*  slot;
3215
2888
#ifdef WIN_ASYNC_IO
3216
2889
        OVERLAPPED*     over;
3217
 
#elif defined(LINUX_NATIVE_AIO)
3218
 
        struct io_event*        aio_event = NULL;
3219
2890
#endif
3220
2891
        ut_a(n > 0);
3221
2892
        ut_a(n_segments > 0);
3222
2893
 
3223
 
        array = static_cast<os_aio_array_t *>(ut_malloc(sizeof(os_aio_array_t)));
 
2894
        array = ut_malloc(sizeof(os_aio_array_t));
3224
2895
 
3225
 
        array->mutex            = os_mutex_create();
 
2896
        array->mutex            = os_mutex_create(NULL);
3226
2897
        array->not_full         = os_event_create(NULL);
3227
2898
        array->is_empty         = os_event_create(NULL);
3228
2899
 
3231
2902
        array->n_slots          = n;
3232
2903
        array->n_segments       = n_segments;
3233
2904
        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)));
 
2905
        array->slots            = ut_malloc(n * sizeof(os_aio_slot_t));
3236
2906
#ifdef __WIN__
3237
 
        array->handles          = ut_malloc(n * sizeof(HANDLE));
 
2907
        array->native_events    = ut_malloc(n * sizeof(os_native_event_t));
3238
2908
#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
2909
        for (i = 0; i < n; i++) {
3276
2910
                slot = os_aio_array_get_nth_slot(array, i);
3277
2911
 
3278
2912
                slot->pos = i;
3279
2913
                slot->reserved = FALSE;
3280
2914
#ifdef WIN_ASYNC_IO
3281
 
                slot->handle = CreateEvent(NULL,TRUE, FALSE, NULL);
 
2915
                slot->event = os_event_create(NULL);
3282
2916
 
3283
2917
                over = &(slot->control);
3284
2918
 
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;
 
2919
                over->hEvent = slot->event->handle;
 
2920
 
 
2921
                *((array->native_events) + i) = over->hEvent;
3294
2922
#endif
3295
2923
        }
3296
2924
 
3297
2925
        return(array);
3298
2926
}
3299
2927
 
3300
 
/************************************************************************//**
3301
 
Frees an aio wait array. */
3302
 
static
 
2928
/****************************************************************************
 
2929
Initializes the asynchronous io system. Calls also os_io_init_simple.
 
2930
Creates a separate aio array for
 
2931
non-ibuf read and write, a third aio array for the ibuf i/o, with just one
 
2932
segment, two aio arrays for log reads and writes with one segment, and a
 
2933
synchronous aio array of the specified size. The combined number of segments
 
2934
in the three first aio arrays is the parameter n_segments given to the
 
2935
function. The caller must create an i/o handler thread for each segment in
 
2936
the four first arrays, but not for the sync aio array. */
 
2937
UNIV_INTERN
3303
2938
void
3304
 
os_aio_array_free(
3305
 
/*==============*/
3306
 
        os_aio_array_t* array)  /*!< in, own: array to free */
3307
 
{
3308
 
#ifdef WIN_ASYNC_IO
3309
 
        ulint   i;
3310
 
 
3311
 
        for (i = 0; i < array->n_slots; i++) {
3312
 
                os_aio_slot_t*  slot = os_aio_array_get_nth_slot(array, i);
3313
 
                CloseHandle(slot->handle);
3314
 
        }
3315
 
#endif /* WIN_ASYNC_IO */
3316
 
 
3317
 
#ifdef __WIN__
3318
 
        ut_free(array->handles);
3319
 
#endif /* __WIN__ */
3320
 
        os_mutex_free(array->mutex);
3321
 
        os_event_free(array->not_full);
3322
 
        os_event_free(array->is_empty);
3323
 
 
3324
 
#if defined(LINUX_NATIVE_AIO)
3325
 
        if (srv_use_native_aio) {
3326
 
                ut_free(array->aio_events);
3327
 
                ut_free(array->aio_ctx);
3328
 
        }
3329
 
#endif /* LINUX_NATIVE_AIO */
3330
 
 
3331
 
        ut_free(array->slots);
3332
 
        ut_free(array);
3333
 
}
3334
 
 
3335
 
/***********************************************************************
3336
 
Initializes the asynchronous io system. Creates one array each for ibuf
3337
 
and log i/o. Also creates one array each for read and write where each
3338
 
array is divided logically into n_read_segs and n_write_segs
3339
 
respectively. The caller must create an i/o handler thread for each
3340
 
segment in these arrays. This function also creates the sync array.
3341
 
No i/o handler thread needs to be created for that */
3342
 
UNIV_INTERN
3343
 
ibool
3344
2939
os_aio_init(
3345
2940
/*========*/
3346
 
        ulint   n_per_seg,      /*<! in: maximum number of pending aio
3347
 
                                operations allowed per segment */
3348
 
        ulint   n_read_segs,    /*<! in: number of reader threads */
3349
 
        ulint   n_write_segs,   /*<! in: number of writer threads */
3350
 
        ulint   n_slots_sync)   /*<! in: number of slots in the sync aio
3351
 
                                array */
 
2941
        ulint   n,              /* in: maximum number of pending aio operations
 
2942
                                allowed; n must be divisible by n_segments */
 
2943
        ulint   n_segments,     /* in: combined number of segments in the four
 
2944
                                first aio arrays; must be >= 4 */
 
2945
        ulint   n_slots_sync)   /* in: number of slots in the sync aio array */
3352
2946
{
 
2947
        ulint   n_read_segs;
 
2948
        ulint   n_write_segs;
 
2949
        ulint   n_per_seg;
3353
2950
        ulint   i;
3354
 
        ulint   n_segments = 2 + n_read_segs + n_write_segs;
3355
2951
 
 
2952
        ut_ad(n % n_segments == 0);
3356
2953
        ut_ad(n_segments >= 4);
3357
2954
 
3358
2955
        os_io_init_simple();
3361
2958
                srv_set_io_thread_op_info(i, "not started yet");
3362
2959
        }
3363
2960
 
 
2961
        n_per_seg = n / n_segments;
 
2962
        n_write_segs = (n_segments - 2) / 2;
 
2963
        n_read_segs = n_segments - 2 - n_write_segs;
3364
2964
 
3365
2965
        /* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
3366
2966
 
3367
2967
        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
2968
 
3372
2969
        srv_io_thread_function[0] = "insert buffer thread";
3373
2970
 
3374
2971
        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
2972
 
3379
2973
        srv_io_thread_function[1] = "log thread";
3380
2974
 
3381
2975
        os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
3382
2976
                                                n_read_segs);
3383
 
        if (os_aio_read_array == NULL) {
3384
 
                goto err_exit;
3385
 
        }
3386
 
 
3387
2977
        for (i = 2; i < 2 + n_read_segs; i++) {
3388
2978
                ut_a(i < SRV_MAX_N_IO_THREADS);
3389
2979
                srv_io_thread_function[i] = "read thread";
3391
2981
 
3392
2982
        os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
3393
2983
                                                 n_write_segs);
3394
 
        if (os_aio_write_array == NULL) {
3395
 
                goto err_exit;
3396
 
        }
3397
 
 
3398
2984
        for (i = 2 + n_read_segs; i < n_segments; i++) {
3399
2985
                ut_a(i < SRV_MAX_N_IO_THREADS);
3400
2986
                srv_io_thread_function[i] = "write thread";
3401
2987
        }
3402
2988
 
3403
2989
        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
2990
 
3409
2991
        os_aio_n_segments = n_segments;
3410
2992
 
3411
2993
        os_aio_validate();
3412
2994
 
3413
 
        os_aio_segment_wait_events = static_cast<os_event_t *>(ut_malloc(n_segments * sizeof(void*)));
 
2995
        os_aio_segment_wait_events = ut_malloc(n_segments * sizeof(void*));
3414
2996
 
3415
2997
        for (i = 0; i < n_segments; i++) {
3416
2998
                os_aio_segment_wait_events[i] = os_event_create(NULL);
3418
3000
 
3419
3001
        os_last_printout = time(NULL);
3420
3002
 
3421
 
        return(TRUE);
3422
 
 
3423
 
err_exit:
3424
 
        return(FALSE);
3425
 
 
3426
 
}
3427
 
 
3428
 
/***********************************************************************
3429
 
Frees the asynchronous io system. */
3430
 
UNIV_INTERN
3431
 
void
3432
 
os_aio_free(void)
3433
 
/*=============*/
3434
 
{
3435
 
        ulint   i;
3436
 
 
3437
 
        os_aio_array_free(os_aio_ibuf_array);
3438
 
        os_aio_ibuf_array = NULL;
3439
 
        os_aio_array_free(os_aio_log_array);
3440
 
        os_aio_log_array = NULL;
3441
 
        os_aio_array_free(os_aio_read_array);
3442
 
        os_aio_read_array = NULL;
3443
 
        os_aio_array_free(os_aio_write_array);
3444
 
        os_aio_write_array = NULL;
3445
 
        os_aio_array_free(os_aio_sync_array);
3446
 
        os_aio_sync_array = NULL;
3447
 
 
3448
 
        for (i = 0; i < os_aio_n_segments; i++) {
3449
 
                os_event_free(os_aio_segment_wait_events[i]);
3450
 
        }
3451
 
 
3452
 
        ut_free(os_aio_segment_wait_events);
3453
 
        os_aio_segment_wait_events = 0;
3454
 
        os_aio_n_segments = 0;
3455
3003
}
3456
3004
 
3457
3005
#ifdef WIN_ASYNC_IO
3458
 
/************************************************************************//**
 
3006
/****************************************************************************
3459
3007
Wakes up all async i/o threads in the array in Windows async i/o at
3460
3008
shutdown. */
3461
3009
static
3462
3010
void
3463
3011
os_aio_array_wake_win_aio_at_shutdown(
3464
3012
/*==================================*/
3465
 
        os_aio_array_t* array)  /*!< in: aio array */
 
3013
        os_aio_array_t* array)  /* in: aio array */
3466
3014
{
3467
3015
        ulint   i;
3468
3016
 
3469
3017
        for (i = 0; i < array->n_slots; i++) {
3470
3018
 
3471
 
                SetEvent((array->slots + i)->handle);
 
3019
                os_event_set((array->slots + i)->event);
3472
3020
        }
3473
3021
}
3474
3022
#endif
3475
3023
 
3476
 
/************************************************************************//**
 
3024
/****************************************************************************
3477
3025
Wakes up all async i/o threads so that they know to exit themselves in
3478
3026
shutdown. */
3479
3027
UNIV_INTERN
3489
3037
        os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
3490
3038
        os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
3491
3039
        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
3040
#endif
3506
3041
        /* This loop wakes up all simulated ai/o threads */
3507
3042
 
3511
3046
        }
3512
3047
}
3513
3048
 
3514
 
/************************************************************************//**
 
3049
/****************************************************************************
3515
3050
Waits until there are no pending writes in os_aio_write_array. There can
3516
3051
be other, synchronous, pending writes. */
3517
3052
UNIV_INTERN
3522
3057
        os_event_wait(os_aio_write_array->is_empty);
3523
3058
}
3524
3059
 
3525
 
/**********************************************************************//**
3526
 
Calculates segment number for a slot.
3527
 
@return segment number (which is the number used by, for example,
3528
 
i/o-handler threads) */
 
3060
/**************************************************************************
 
3061
Calculates segment number for a slot. */
3529
3062
static
3530
3063
ulint
3531
3064
os_aio_get_segment_no_from_slot(
3532
3065
/*============================*/
3533
 
        os_aio_array_t* array,  /*!< in: aio wait array */
3534
 
        os_aio_slot_t*  slot)   /*!< in: slot in this array */
 
3066
                                /* out: segment number (which is the number
 
3067
                                used by, for example, i/o-handler threads) */
 
3068
        os_aio_array_t* array,  /* in: aio wait array */
 
3069
        os_aio_slot_t*  slot)   /* in: slot in this array */
3535
3070
{
3536
3071
        ulint   segment;
3537
3072
        ulint   seg_len;
3559
3094
        return(segment);
3560
3095
}
3561
3096
 
3562
 
/**********************************************************************//**
3563
 
Calculates local segment number and aio array from global segment number.
3564
 
@return local segment number within the aio array */
 
3097
/**************************************************************************
 
3098
Calculates local segment number and aio array from global segment number. */
3565
3099
static
3566
3100
ulint
3567
3101
os_aio_get_array_and_local_segment(
3568
3102
/*===============================*/
3569
 
        os_aio_array_t** array,         /*!< out: aio wait array */
3570
 
        ulint            global_segment)/*!< in: global segment number */
 
3103
                                        /* out: local segment number within
 
3104
                                        the aio array */
 
3105
        os_aio_array_t** array,         /* out: aio wait array */
 
3106
        ulint            global_segment)/* in: global segment number */
3571
3107
{
3572
3108
        ulint   segment;
3573
3109
 
3594
3130
        return(segment);
3595
3131
}
3596
3132
 
3597
 
/*******************************************************************//**
 
3133
/***********************************************************************
3598
3134
Requests for a slot in the aio array. If no slot is available, waits until
3599
 
not_full-event becomes signaled.
3600
 
@return pointer to slot */
 
3135
not_full-event becomes signaled. */
3601
3136
static
3602
3137
os_aio_slot_t*
3603
3138
os_aio_array_reserve_slot(
3604
3139
/*======================*/
3605
 
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3606
 
        os_aio_array_t* array,  /*!< in: aio array */
3607
 
        fil_node_t*     message1,/*!< in: message to be passed along with
3608
 
                                the aio operation */
3609
 
        void*           message2,/*!< in: message to be passed along with
3610
 
                                the aio operation */
3611
 
        os_file_t       file,   /*!< in: file handle */
3612
 
        const char*     name,   /*!< in: name of the file or path as a
 
3140
                                /* out: pointer to slot */
 
3141
        ulint           type,   /* in: OS_FILE_READ or OS_FILE_WRITE */
 
3142
        os_aio_array_t* array,  /* in: aio array */
 
3143
        fil_node_t*     message1,/* in: message to be passed along with
 
3144
                                the aio operation */
 
3145
        void*           message2,/* in: message to be passed along with
 
3146
                                the aio operation */
 
3147
        os_file_t       file,   /* in: file handle */
 
3148
        const char*     name,   /* in: name of the file or path as a
3613
3149
                                null-terminated string */
3614
 
        void*           buf,    /*!< in: buffer where to read or from which
 
3150
        void*           buf,    /* in: buffer where to read or from which
3615
3151
                                to write */
3616
 
        ulint           offset, /*!< in: least significant 32 bits of file
3617
 
                                offset */
3618
 
        ulint           offset_high, /*!< in: most significant 32 bits of
3619
 
                                offset */
3620
 
        ulint           len)    /*!< in: length of the block to read or write */
 
3152
        ulint           offset, /* in: least significant 32 bits of file
 
3153
                                offset */
 
3154
        ulint           offset_high, /* in: most significant 32 bits of
 
3155
                                offset */
 
3156
        ulint           len)    /* in: length of the block to read or write */
3621
3157
{
3622
 
        os_aio_slot_t*  slot = NULL;
 
3158
        os_aio_slot_t*  slot;
3623
3159
#ifdef WIN_ASYNC_IO
3624
3160
        OVERLAPPED*     control;
3625
 
 
3626
 
#elif defined(LINUX_NATIVE_AIO)
3627
 
 
3628
 
        struct iocb*    iocb;
3629
 
        off_t           aio_offset;
3630
 
 
3631
3161
#endif
3632
3162
        ulint           i;
3633
 
        ulint           counter;
3634
 
        ulint           slots_per_seg;
3635
 
        ulint           local_seg;
3636
 
 
3637
 
#ifdef WIN_ASYNC_IO
3638
 
        ut_a((len & 0xFFFFFFFFUL) == len);
3639
 
#endif
3640
 
 
3641
 
        /* No need of a mutex. Only reading constant fields */
3642
 
        slots_per_seg = array->n_slots / array->n_segments;
3643
 
 
3644
 
        /* We attempt to keep adjacent blocks in the same local
3645
 
        segment. This can help in merging IO requests when we are
3646
 
        doing simulated AIO */
3647
 
        local_seg = (offset >> (UNIV_PAGE_SIZE_SHIFT + 6))
3648
 
                    % array->n_segments;
3649
 
 
3650
3163
loop:
3651
3164
        os_mutex_enter(array->mutex);
3652
3165
 
3653
3166
        if (array->n_reserved == array->n_slots) {
3654
3167
                os_mutex_exit(array->mutex);
3655
3168
 
3656
 
                if (!srv_use_native_aio) {
 
3169
                if (!os_aio_use_native_aio) {
3657
3170
                        /* If the handler threads are suspended, wake them
3658
3171
                        so that we get more slots */
3659
3172
 
3665
3178
                goto loop;
3666
3179
        }
3667
3180
 
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;
 
3181
        for (i = 0;; i++) {
3675
3182
                slot = os_aio_array_get_nth_slot(array, i);
3676
3183
 
3677
3184
                if (slot->reserved == FALSE) {
3678
 
                        goto found;
 
3185
                        break;
3679
3186
                }
3680
3187
        }
3681
3188
 
3682
 
        /* We MUST always be able to get hold of a reserved slot. */
3683
 
        ut_error;
3684
 
 
3685
 
found:
3686
 
        ut_a(slot->reserved == FALSE);
3687
3189
        array->n_reserved++;
3688
3190
 
3689
3191
        if (array->n_reserved == 1) {
3702
3204
        slot->name     = name;
3703
3205
        slot->len      = len;
3704
3206
        slot->type     = type;
3705
 
        slot->buf      = static_cast<unsigned char *>(buf);
 
3207
        slot->buf      = buf;
3706
3208
        slot->offset   = offset;
3707
3209
        slot->offset_high = offset_high;
3708
3210
        slot->io_already_done = FALSE;
3711
3213
        control = &(slot->control);
3712
3214
        control->Offset = (DWORD)offset;
3713
3215
        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 */
 
3216
        os_event_reset(slot->event);
 
3217
#endif
 
3218
 
3751
3219
        os_mutex_exit(array->mutex);
3752
3220
 
3753
3221
        return(slot);
3754
3222
}
3755
3223
 
3756
 
/*******************************************************************//**
 
3224
/***********************************************************************
3757
3225
Frees a slot in the aio array. */
3758
3226
static
3759
3227
void
3760
3228
os_aio_array_free_slot(
3761
3229
/*===================*/
3762
 
        os_aio_array_t* array,  /*!< in: aio array */
3763
 
        os_aio_slot_t*  slot)   /*!< in: pointer to slot */
 
3230
        os_aio_array_t* array,  /* in: aio array */
 
3231
        os_aio_slot_t*  slot)   /* in: pointer to slot */
3764
3232
{
3765
3233
        ut_ad(array);
3766
3234
        ut_ad(slot);
3782
3250
        }
3783
3251
 
3784
3252
#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
 
 
 
3253
        os_event_reset(slot->event);
3802
3254
#endif
3803
3255
        os_mutex_exit(array->mutex);
3804
3256
}
3805
3257
 
3806
 
/**********************************************************************//**
 
3258
/**************************************************************************
3807
3259
Wakes up a simulated aio i/o-handler thread if it has something to do. */
3808
3260
static
3809
3261
void
3810
3262
os_aio_simulated_wake_handler_thread(
3811
3263
/*=================================*/
3812
 
        ulint   global_segment) /*!< in: the number of the segment in the aio
 
3264
        ulint   global_segment) /* in: the number of the segment in the aio
3813
3265
                                arrays */
3814
3266
{
3815
3267
        os_aio_array_t* array;
3818
3270
        ulint           n;
3819
3271
        ulint           i;
3820
3272
 
3821
 
        ut_ad(!srv_use_native_aio);
 
3273
        ut_ad(!os_aio_use_native_aio);
3822
3274
 
3823
3275
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
3824
3276
 
3845
3297
        }
3846
3298
}
3847
3299
 
3848
 
/**********************************************************************//**
 
3300
/**************************************************************************
3849
3301
Wakes up simulated aio i/o-handler threads if they have something to do. */
3850
3302
UNIV_INTERN
3851
3303
void
3854
3306
{
3855
3307
        ulint   i;
3856
3308
 
3857
 
        if (srv_use_native_aio) {
 
3309
        if (os_aio_use_native_aio) {
3858
3310
                /* We do not use simulated aio: do nothing */
3859
3311
 
3860
3312
                return;
3867
3319
        }
3868
3320
}
3869
3321
 
3870
 
/**********************************************************************//**
 
3322
/**************************************************************************
3871
3323
This function can be called if one wants to post a batch of reads and
3872
3324
prefers an i/o-handler thread to handle them all at once later. You must
3873
3325
call os_aio_simulated_wake_handler_threads later to ensure the threads
3877
3329
os_aio_simulated_put_read_threads_to_sleep(void)
3878
3330
/*============================================*/
3879
3331
{
3880
 
 
3881
 
/* The idea of putting background IO threads to sleep is only for
3882
 
Windows when using simulated AIO. Windows XP seems to schedule
3883
 
background threads too eagerly to allow for coalescing during
3884
 
readahead requests. */
3885
 
#ifdef __WIN__
3886
3332
        os_aio_array_t* array;
3887
3333
        ulint           g;
3888
3334
 
3889
 
        if (srv_use_native_aio) {
3890
 
                /* We do not use simulated aio: do nothing */
3891
 
 
3892
 
                return;
3893
 
        }
3894
 
 
3895
3335
        os_aio_recommend_sleep_for_read_threads = TRUE;
3896
3336
 
3897
3337
        for (g = 0; g < os_aio_n_segments; g++) {
3902
3342
                        os_event_reset(os_aio_segment_wait_events[g]);
3903
3343
                }
3904
3344
        }
3905
 
#endif /* __WIN__ */
3906
 
}
3907
 
 
3908
 
#if defined(LINUX_NATIVE_AIO)
3909
 
/*******************************************************************//**
3910
 
Dispatch an AIO request to the kernel.
3911
 
@return TRUE on success. */
3912
 
static
3913
 
ibool
3914
 
os_aio_linux_dispatch(
3915
 
/*==================*/
3916
 
        os_aio_array_t* array,  /*!< in: io request array. */
3917
 
        os_aio_slot_t*  slot)   /*!< in: an already reserved slot. */
3918
 
{
3919
 
        int             ret;
3920
 
        ulint           io_ctx_index;
3921
 
        struct iocb*    iocb;
3922
 
 
3923
 
        ut_ad(slot != NULL);
3924
 
        ut_ad(array);
3925
 
 
3926
 
        ut_a(slot->reserved);
3927
 
 
3928
 
        /* Find out what we are going to work with.
3929
 
        The iocb struct is directly in the slot.
3930
 
        The io_context is one per segment. */
3931
 
 
3932
 
        iocb = &slot->control;
3933
 
        io_ctx_index = (slot->pos * array->n_segments) / array->n_slots;
3934
 
 
3935
 
        ret = io_submit(array->aio_ctx[io_ctx_index], 1, &iocb);
3936
 
 
3937
 
#if defined(UNIV_AIO_DEBUG)
3938
 
        fprintf(stderr,
3939
 
                "io_submit[%c] ret[%d]: slot[%p] ctx[%p] seg[%lu]\n",
3940
 
                (slot->type == OS_FILE_WRITE) ? 'w' : 'r', ret, slot,
3941
 
                array->aio_ctx[io_ctx_index], (ulong)io_ctx_index);
3942
 
#endif
3943
 
 
3944
 
        /* io_submit returns number of successfully
3945
 
        queued requests or -errno. */
3946
 
        if (UNIV_UNLIKELY(ret != 1)) {
3947
 
                errno = -ret;
3948
 
                return(FALSE);
3949
 
        }
3950
 
 
3951
 
        return(TRUE);
3952
 
}
3953
 
#endif /* LINUX_NATIVE_AIO */
3954
 
 
3955
 
 
3956
 
/*******************************************************************//**
3957
 
NOTE! Use the corresponding macro os_aio(), not directly this function!
3958
 
Requests an asynchronous i/o operation.
3959
 
@return TRUE if request was queued successfully, FALSE if fail */
 
3345
}
 
3346
 
 
3347
/***********************************************************************
 
3348
Requests an asynchronous i/o operation. */
3960
3349
UNIV_INTERN
3961
3350
ibool
3962
 
os_aio_func(
3963
 
/*========*/
3964
 
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3965
 
        ulint           mode,   /*!< in: OS_AIO_NORMAL, ..., possibly ORed
 
3351
os_aio(
 
3352
/*===*/
 
3353
                                /* out: TRUE if request was queued
 
3354
                                successfully, FALSE if fail */
 
3355
        ulint           type,   /* in: OS_FILE_READ or OS_FILE_WRITE */
 
3356
        ulint           mode,   /* in: OS_AIO_NORMAL, ..., possibly ORed
3966
3357
                                to OS_AIO_SIMULATED_WAKE_LATER: the
3967
3358
                                last flag advises this function not to wake
3968
3359
                                i/o-handler threads, but the caller will
3975
3366
                                because i/os are not actually handled until
3976
3367
                                all have been posted: use with great
3977
3368
                                caution! */
3978
 
        const char*     name,   /*!< in: name of the file or path as a
 
3369
        const char*     name,   /* in: name of the file or path as a
3979
3370
                                null-terminated string */
3980
 
        os_file_t       file,   /*!< in: handle to a file */
3981
 
        void*           buf,    /*!< in: buffer where to read or from which
 
3371
        os_file_t       file,   /* in: handle to a file */
 
3372
        void*           buf,    /* in: buffer where to read or from which
3982
3373
                                to write */
3983
 
        ulint           offset, /*!< in: least significant 32 bits of file
 
3374
        ulint           offset, /* in: least significant 32 bits of file
3984
3375
                                offset where to read or write */
3985
 
        ulint           offset_high, /*!< in: most significant 32 bits of
 
3376
        ulint           offset_high, /* in: most significant 32 bits of
3986
3377
                                offset */
3987
 
        ulint           n,      /*!< in: number of bytes to read or write */
3988
 
        fil_node_t*     message1,/*!< in: message for the aio handler
3989
 
                                (can be used to identify a completed
3990
 
                                aio operation); ignored if mode is
3991
 
                                OS_AIO_SYNC */
3992
 
        void*           message2)/*!< in: message for the aio handler
3993
 
                                (can be used to identify a completed
3994
 
                                aio operation); ignored if mode is
3995
 
                                OS_AIO_SYNC */
 
3378
        ulint           n,      /* in: number of bytes to read or write */
 
3379
        fil_node_t*     message1,/* in: messages for the aio handler (these
 
3380
                                can be used to identify a completed aio
 
3381
                                operation); if mode is OS_AIO_SYNC, these
 
3382
                                are ignored */
 
3383
        void*           message2)
3996
3384
{
3997
3385
        os_aio_array_t* array;
3998
3386
        os_aio_slot_t*  slot;
4003
3391
        struct fil_node_struct * dummy_mess1;
4004
3392
        void*           dummy_mess2;
4005
3393
        ulint           dummy_type;
4006
 
#endif /* WIN_ASYNC_IO */
4007
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
 
3394
#endif
 
3395
        ulint           err             = 0;
4008
3396
        ibool           retry;
4009
 
#endif
4010
3397
        ulint           wake_later;
4011
3398
 
4012
3399
        ut_ad(file);
4015
3402
        ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
4016
3403
        ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
4017
3404
        ut_ad(os_aio_validate());
4018
 
#ifdef WIN_ASYNC_IO
4019
 
        ut_ad((n & 0xFFFFFFFFUL) == n);
4020
 
#endif
4021
3405
 
4022
3406
        wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
4023
3407
        mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
4024
3408
 
4025
3409
        if (mode == OS_AIO_SYNC
4026
3410
#ifdef WIN_ASYNC_IO
4027
 
            && !srv_use_native_aio
4028
 
#endif /* WIN_ASYNC_IO */
 
3411
            && !os_aio_use_native_aio
 
3412
#endif
4029
3413
            ) {
4030
3414
                /* This is actually an ordinary synchronous read or write:
4031
3415
                no need to use an i/o-handler thread. NOTE that if we use
4044
3428
                return(os_file_write(name, file, buf, offset, offset_high, n));
4045
3429
        }
4046
3430
 
4047
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
4048
3431
try_again:
4049
 
#endif
4050
3432
        if (mode == OS_AIO_NORMAL) {
4051
3433
                if (type == OS_FILE_READ) {
4052
3434
                        array = os_aio_read_array;
4066
3448
                array = os_aio_log_array;
4067
3449
        } else if (mode == OS_AIO_SYNC) {
4068
3450
                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
3451
        } else {
4075
3452
                array = NULL; /* Eliminate compiler warning */
4076
3453
                ut_error;
4079
3456
        slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
4080
3457
                                         name, buf, offset, offset_high, n);
4081
3458
        if (type == OS_FILE_READ) {
4082
 
                if (srv_use_native_aio) {
 
3459
                if (os_aio_use_native_aio) {
 
3460
#ifdef WIN_ASYNC_IO
4083
3461
                        os_n_file_reads++;
4084
 
                        os_bytes_read_since_printout += n;
4085
 
#ifdef WIN_ASYNC_IO
 
3462
                        os_bytes_read_since_printout += len;
 
3463
 
4086
3464
                        ret = ReadFile(file, buf, (DWORD)n, &len,
4087
3465
                                       &(slot->control));
4088
 
 
4089
 
#elif defined(LINUX_NATIVE_AIO)
4090
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4091
 
                                goto err_exit;
4092
 
                        }
4093
3466
#endif
4094
3467
                } else {
4095
3468
                        if (!wake_later) {
4099
3472
                        }
4100
3473
                }
4101
3474
        } else if (type == OS_FILE_WRITE) {
4102
 
                if (srv_use_native_aio) {
 
3475
                if (os_aio_use_native_aio) {
 
3476
#ifdef WIN_ASYNC_IO
4103
3477
                        os_n_file_writes++;
4104
 
#ifdef WIN_ASYNC_IO
4105
3478
                        ret = WriteFile(file, buf, (DWORD)n, &len,
4106
3479
                                        &(slot->control));
4107
 
 
4108
 
#elif defined(LINUX_NATIVE_AIO)
4109
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4110
 
                                goto err_exit;
4111
 
                        }
4112
3480
#endif
4113
3481
                } else {
4114
3482
                        if (!wake_later) {
4122
3490
        }
4123
3491
 
4124
3492
#ifdef WIN_ASYNC_IO
4125
 
        if (srv_use_native_aio) {
 
3493
        if (os_aio_use_native_aio) {
4126
3494
                if ((ret && len == n)
4127
3495
                    || (!ret && GetLastError() == ERROR_IO_PENDING)) {
4128
3496
                        /* aio was queued successfully! */
4145
3513
                        return(TRUE);
4146
3514
                }
4147
3515
 
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:
 
3516
                err = 1; /* Fall through the next if */
 
3517
        }
 
3518
#endif
 
3519
        if (err == 0) {
 
3520
                /* aio was queued successfully! */
 
3521
 
 
3522
                return(TRUE);
 
3523
        }
 
3524
 
4156
3525
        os_aio_array_free_slot(array, slot);
4157
3526
 
4158
3527
        retry = os_file_handle_error(name,
4164
3533
        }
4165
3534
 
4166
3535
        return(FALSE);
4167
 
#endif /* LINUX_NATIVE_AIO || WIN_ASYNC_IO */
4168
3536
}
4169
3537
 
4170
3538
#ifdef WIN_ASYNC_IO
4171
 
/**********************************************************************//**
 
3539
/**************************************************************************
4172
3540
This function is only used in Windows asynchronous i/o.
4173
3541
Waits for an aio operation to complete. This function is used to wait the
4174
3542
for completed requests. The aio array of pending requests is divided
4175
3543
into segments. The thread specifies which segment or slot it wants to wait
4176
3544
for. NOTE: this function will also take care of freeing the aio slot,
4177
 
therefore no other thread is allowed to do the freeing!
4178
 
@return TRUE if the aio operation succeeded */
 
3545
therefore no other thread is allowed to do the freeing! */
4179
3546
UNIV_INTERN
4180
3547
ibool
4181
3548
os_aio_windows_handle(
4182
3549
/*==================*/
4183
 
        ulint   segment,        /*!< in: the number of the segment in the aio
 
3550
                                /* out: TRUE if the aio operation succeeded */
 
3551
        ulint   segment,        /* in: the number of the segment in the aio
4184
3552
                                arrays to wait for; segment 0 is the ibuf
4185
3553
                                i/o thread, segment 1 the log i/o thread,
4186
3554
                                then follow the non-ibuf read threads, and as
4188
3556
                                this is ULINT_UNDEFINED, then it means that
4189
3557
                                sync aio is used, and this parameter is
4190
3558
                                ignored */
4191
 
        ulint   pos,            /*!< this parameter is used only in sync aio:
 
3559
        ulint   pos,            /* this parameter is used only in sync aio:
4192
3560
                                wait for the aio slot at this position */
4193
 
        fil_node_t**message1,   /*!< out: the messages passed with the aio
 
3561
        fil_node_t**message1,   /* out: the messages passed with the aio
4194
3562
                                request; note that also in the case where
4195
3563
                                the aio operation failed, these output
4196
3564
                                parameters are valid and can be used to
4197
3565
                                restart the operation, for example */
4198
3566
        void**  message2,
4199
 
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
 
3567
        ulint*  type)           /* out: OS_FILE_WRITE or ..._READ */
4200
3568
{
4201
3569
        ulint           orig_seg        = segment;
4202
3570
        os_aio_array_t* array;
4206
3574
        ibool           ret_val;
4207
3575
        BOOL            ret;
4208
3576
        DWORD           len;
4209
 
        BOOL            retry           = FALSE;
4210
3577
 
4211
3578
        if (segment == ULINT_UNDEFINED) {
4212
3579
                array = os_aio_sync_array;
4224
3591
        n = array->n_slots / array->n_segments;
4225
3592
 
4226
3593
        if (array == os_aio_sync_array) {
4227
 
                WaitForSingleObject(
4228
 
                        os_aio_array_get_nth_slot(array, pos)->handle,
4229
 
                        INFINITE);
 
3594
                os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
4230
3595
                i = pos;
4231
3596
        } else {
4232
3597
                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);
 
3598
                i = os_event_wait_multiple(n,
 
3599
                                           (array->native_events)
 
3600
                                           + segment * n);
4241
3601
        }
4242
3602
 
4243
3603
        os_mutex_enter(array->mutex);
4264
3624
#ifdef UNIV_DO_FLUSH
4265
3625
                if (slot->type == OS_FILE_WRITE
4266
3626
                    && !os_do_not_call_flush_at_each_write) {
4267
 
                        if (!os_file_flush(slot->file)) {
4268
 
                                ut_error;
4269
 
                        }
 
3627
                        ut_a(TRUE == os_file_flush(slot->file));
4270
3628
                }
4271
3629
#endif /* UNIV_DO_FLUSH */
4272
 
        } else if (os_file_handle_error(slot->name, "Windows aio")) {
4273
 
 
4274
 
                retry = TRUE;
4275
3630
        } else {
 
3631
                os_file_handle_error(slot->name, "Windows aio");
4276
3632
 
4277
3633
                ret_val = FALSE;
4278
3634
        }
4279
3635
 
4280
3636
        os_mutex_exit(array->mutex);
4281
3637
 
4282
 
        if (retry) {
4283
 
                /* retry failed read/write operation synchronously.
4284
 
                No need to hold array->mutex. */
4285
 
 
4286
 
#ifdef UNIV_PFS_IO
4287
 
                /* This read/write does not go through os_file_read
4288
 
                and os_file_write APIs, need to register with
4289
 
                performance schema explicitly here. */
4290
 
                struct PSI_file_locker* locker = NULL;
4291
 
                register_pfs_file_io_begin(locker, slot->file, slot->len,
4292
 
                                           (slot->type == OS_FILE_WRITE)
4293
 
                                                ? PSI_FILE_WRITE
4294
 
                                                : PSI_FILE_READ,
4295
 
                                            __FILE__, __LINE__);
4296
 
#endif
4297
 
 
4298
 
                ut_a((slot->len & 0xFFFFFFFFUL) == slot->len);
4299
 
 
4300
 
                switch (slot->type) {
4301
 
                case OS_FILE_WRITE:
4302
 
                        ret = WriteFile(slot->file, slot->buf,
4303
 
                                        (DWORD) slot->len, &len,
4304
 
                                        &(slot->control));
4305
 
 
4306
 
                        break;
4307
 
                case OS_FILE_READ:
4308
 
                        ret = ReadFile(slot->file, slot->buf,
4309
 
                                       (DWORD) slot->len, &len,
4310
 
                                       &(slot->control));
4311
 
 
4312
 
                        break;
4313
 
                default:
4314
 
                        ut_error;
4315
 
                }
4316
 
 
4317
 
#ifdef UNIV_PFS_IO
4318
 
                register_pfs_file_io_end(locker, len);
4319
 
#endif
4320
 
 
4321
 
                if (!ret && GetLastError() == ERROR_IO_PENDING) {
4322
 
                        /* aio was queued successfully!
4323
 
                        We want a synchronous i/o operation on a
4324
 
                        file where we also use async i/o: in Windows
4325
 
                        we must use the same wait mechanism as for
4326
 
                        async i/o */
4327
 
 
4328
 
                        ret = GetOverlappedResult(slot->file,
4329
 
                                                  &(slot->control),
4330
 
                                                  &len, TRUE);
4331
 
                }
4332
 
 
4333
 
                ret_val = ret && len == slot->len;
4334
 
        }
4335
 
 
4336
3638
        os_aio_array_free_slot(array, slot);
4337
3639
 
4338
3640
        return(ret_val);
4339
3641
}
4340
3642
#endif
4341
3643
 
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
 
/**********************************************************************//**
 
3644
/**************************************************************************
4593
3645
Does simulated aio. This function should be called by an i/o-handler
4594
 
thread.
4595
 
@return TRUE if the aio operation succeeded */
 
3646
thread. */
4596
3647
UNIV_INTERN
4597
3648
ibool
4598
3649
os_aio_simulated_handle(
4599
3650
/*====================*/
4600
 
        ulint   global_segment, /*!< in: the number of the segment in the aio
 
3651
                                /* out: TRUE if the aio operation succeeded */
 
3652
        ulint   global_segment, /* in: the number of the segment in the aio
4601
3653
                                arrays to wait for; segment 0 is the ibuf
4602
3654
                                i/o thread, segment 1 the log i/o thread,
4603
3655
                                then follow the non-ibuf read threads, and as
4604
3656
                                the last are the non-ibuf write threads */
4605
 
        fil_node_t**message1,   /*!< out: the messages passed with the aio
 
3657
        fil_node_t**message1,   /* out: the messages passed with the aio
4606
3658
                                request; note that also in the case where
4607
3659
                                the aio operation failed, these output
4608
3660
                                parameters are valid and can be used to
4609
3661
                                restart the operation, for example */
4610
3662
        void**  message2,
4611
 
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
 
3663
        ulint*  type)           /* out: OS_FILE_WRITE or ..._READ */
4612
3664
{
4613
3665
        os_aio_array_t* array;
4614
3666
        ulint           segment;
4627
3679
        ulint           n;
4628
3680
        ulint           i;
4629
3681
 
4630
 
        /* Fix compiler warning */
4631
 
        *consecutive_ios = NULL;
4632
 
 
4633
3682
        memset(consecutive_ios, 0, sizeof(os_aio_slot_t*) * OS_AIO_MERGE_N_CONSECUTIVE);
4634
3683
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
4635
3684
 
4742
3791
                goto wait_for_io;
4743
3792
        }
4744
3793
 
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
3794
        slot = consecutive_ios[0];
4751
3795
 
4752
3796
        /* Check if there are several consecutive blocks to read or write */
4797
3841
                combined_buf = slot->buf;
4798
3842
                combined_buf2 = NULL;
4799
3843
        } else {
4800
 
                combined_buf2 = static_cast<unsigned char *>(ut_malloc(total_len + UNIV_PAGE_SIZE));
 
3844
                combined_buf2 = ut_malloc(total_len + UNIV_PAGE_SIZE);
4801
3845
 
4802
3846
                ut_a(combined_buf2);
4803
3847
 
4804
 
                combined_buf = static_cast<unsigned char *>(ut_align(combined_buf2, UNIV_PAGE_SIZE));
 
3848
                combined_buf = ut_align(combined_buf2, UNIV_PAGE_SIZE);
4805
3849
        }
4806
3850
 
4807
3851
        /* We release the array mutex for the time of the i/o: NOTE that
4919
3963
        goto restart;
4920
3964
}
4921
3965
 
4922
 
/**********************************************************************//**
4923
 
Validates the consistency of an aio array.
4924
 
@return TRUE if ok */
 
3966
/**************************************************************************
 
3967
Validates the consistency of an aio array. */
4925
3968
static
4926
3969
ibool
4927
3970
os_aio_array_validate(
4928
3971
/*==================*/
4929
 
        os_aio_array_t* array)  /*!< in: aio wait array */
 
3972
                                /* out: TRUE if ok */
 
3973
        os_aio_array_t* array)  /* in: aio wait array */
4930
3974
{
4931
3975
        os_aio_slot_t*  slot;
4932
3976
        ulint           n_reserved      = 0;
4955
3999
        return(TRUE);
4956
4000
}
4957
4001
 
4958
 
/**********************************************************************//**
4959
 
Validates the consistency the aio system.
4960
 
@return TRUE if ok */
 
4002
/**************************************************************************
 
4003
Validates the consistency the aio system. */
4961
4004
UNIV_INTERN
4962
4005
ibool
4963
4006
os_aio_validate(void)
4964
4007
/*=================*/
 
4008
                                /* out: TRUE if ok */
4965
4009
{
4966
4010
        os_aio_array_validate(os_aio_read_array);
4967
4011
        os_aio_array_validate(os_aio_write_array);
4972
4016
        return(TRUE);
4973
4017
}
4974
4018
 
4975
 
/**********************************************************************//**
4976
 
Prints pending IO requests per segment of an aio array.
4977
 
We probably don't need per segment statistics but they can help us
4978
 
during development phase to see if the IO requests are being
4979
 
distributed as expected. */
4980
 
static
4981
 
void
4982
 
os_aio_print_segment_info(
4983
 
/*======================*/
4984
 
        FILE*           file,   /*!< in: file where to print */
4985
 
        ulint*          n_seg,  /*!< in: pending IO array */
4986
 
        os_aio_array_t* array)  /*!< in: array to process */
4987
 
{
4988
 
        ulint   i;
4989
 
 
4990
 
        ut_ad(array);
4991
 
        ut_ad(n_seg);
4992
 
        ut_ad(array->n_segments > 0);
4993
 
 
4994
 
        if (array->n_segments == 1) {
4995
 
                return;
4996
 
        }
4997
 
 
4998
 
        fprintf(file, " [");
4999
 
        for (i = 0; i < array->n_segments; i++) {
5000
 
                if (i != 0) {
5001
 
                        fprintf(file, ", ");
5002
 
                }
5003
 
 
5004
 
                fprintf(file, "%lu", n_seg[i]);
5005
 
        }
5006
 
        fprintf(file, "] ");
5007
 
}
5008
 
 
5009
 
/**********************************************************************//**
 
4019
/**************************************************************************
5010
4020
Prints info of the aio arrays. */
5011
4021
UNIV_INTERN
5012
4022
void
5013
4023
os_aio_print(
5014
4024
/*=========*/
5015
 
        FILE*   file)   /*!< in: file where to print */
 
4025
        FILE*   file)   /* in: file where to print */
5016
4026
{
5017
4027
        os_aio_array_t* array;
5018
4028
        os_aio_slot_t*  slot;
5019
4029
        ulint           n_reserved;
5020
 
        ulint           n_res_seg[SRV_MAX_N_IO_THREADS];
5021
4030
        time_t          current_time;
5022
4031
        double          time_elapsed;
5023
4032
        double          avg_bytes_read;
5050
4059
 
5051
4060
        n_reserved = 0;
5052
4061
 
5053
 
        memset(n_res_seg, 0x0, sizeof(n_res_seg));
5054
 
 
5055
4062
        for (i = 0; i < array->n_slots; i++) {
5056
 
                ulint   seg_no;
5057
 
 
5058
4063
                slot = os_aio_array_get_nth_slot(array, i);
5059
4064
 
5060
 
                seg_no = (i * array->n_segments) / array->n_slots;
5061
4065
                if (slot->reserved) {
5062
4066
                        n_reserved++;
5063
 
                        n_res_seg[seg_no]++;
5064
4067
#if 0
5065
4068
                        fprintf(stderr, "Reserved slot, messages %p %p\n",
5066
4069
                                (void*) slot->message1,
5074
4077
 
5075
4078
        fprintf(file, " %lu", (ulong) n_reserved);
5076
4079
 
5077
 
        os_aio_print_segment_info(file, n_res_seg, array);
5078
 
 
5079
4080
        os_mutex_exit(array->mutex);
5080
4081
 
5081
4082
        if (array == os_aio_read_array) {
5152
4153
        os_last_printout = current_time;
5153
4154
}
5154
4155
 
5155
 
/**********************************************************************//**
 
4156
/**************************************************************************
5156
4157
Refreshes the statistics used to print per-second averages. */
5157
4158
UNIV_INTERN
5158
4159
void
5168
4169
}
5169
4170
 
5170
4171
#ifdef UNIV_DEBUG
5171
 
/**********************************************************************//**
 
4172
/**************************************************************************
5172
4173
Checks that all slots in the system have been freed, that is, there are
5173
 
no pending io operations.
5174
 
@return TRUE if all free */
 
4174
no pending io operations. */
5175
4175
UNIV_INTERN
5176
4176
ibool
5177
4177
os_aio_all_slots_free(void)
5178
4178
/*=======================*/
 
4179
                                /* out: TRUE if all free */
5179
4180
{
5180
4181
        os_aio_array_t* array;
5181
4182
        ulint           n_res   = 0;
5228
4229
        return(FALSE);
5229
4230
}
5230
4231
#endif /* UNIV_DEBUG */
5231
 
 
5232
 
#endif /* !UNIV_HOTBACKUP */