15
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
17
*****************************************************************************/
18
/***********************************************************************
20
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
21
Copyright (c) 2009, Percona Inc.
23
Portions of this file contain modifications contributed and copyrighted
24
by Percona Inc.. Those modifications are
25
gratefully acknowledged and are described briefly in the InnoDB
26
documentation. The contributions by Percona Inc. are incorporated with
27
their permission, and subject to the conditions contained in the file
30
This program is free software; you can redistribute it and/or modify it
31
under the terms of the GNU General Public License as published by the
32
Free Software Foundation; version 2 of the License.
34
This program is distributed in the hope that it will be useful, but
35
WITHOUT ANY WARRANTY; without even the implied warranty of
36
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
37
Public License for more details.
39
You should have received a copy of the GNU General Public License along
40
with this program; if not, write to the Free Software Foundation, Inc.,
41
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43
***********************************************************************/
45
/**************************************************//**
19
/******************************************************
47
20
The interface to the operating system file i/o primitives
49
22
Created 10/21/1995 Heikki Tuuri
50
23
*******************************************************/
52
25
#include "os0file.h"
27
#include "os0thread.h"
53
28
#include "ut0mem.h"
54
29
#include "srv0srv.h"
55
30
#include "srv0start.h"
56
31
#include "fil0fil.h"
57
32
#include "buf0buf.h"
34
#if defined(UNIV_HOTBACKUP) && defined(__WIN__)
35
/* Add includes for the _stat() call to compile on Windows */
36
#include <sys/types.h>
62
#ifndef UNIV_HOTBACKUP
64
# include "os0thread.h"
65
#else /* !UNIV_HOTBACKUP */
67
/* Add includes for the _stat() call to compile on Windows */
68
# include <sys/types.h>
69
# include <sys/stat.h>
71
#endif /* !UNIV_HOTBACKUP */
39
#endif /* UNIV_HOTBACKUP */
73
41
/* This specifies the file permissions InnoDB uses when it creates files in
74
42
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
78
/** Umask for creating files */
79
46
UNIV_INTERN ulint os_innodb_umask
80
47
= S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
82
/** Umask for creating files */
83
49
UNIV_INTERN ulint os_innodb_umask = 0;
100
65
/* In simulated aio, merge at most this many consecutive i/os */
101
66
#define OS_AIO_MERGE_N_CONSECUTIVE 64
103
/** If this flag is TRUE, then we will use the native aio of the
68
/* If this flag is TRUE, then we will use the native aio of the
104
69
OS (provided we compiled Innobase with it in), otherwise we will
105
70
use simulated aio we build below with threads */
107
72
UNIV_INTERN ibool os_aio_use_native_aio = FALSE;
109
/** Flag: enable debug printout for asynchronous i/o */
110
74
UNIV_INTERN ibool os_aio_print_debug = FALSE;
112
/** The asynchronous i/o array slot structure */
76
/* The aio array slot structure */
113
77
typedef struct os_aio_slot_struct os_aio_slot_t;
115
/** The asynchronous i/o array slot structure */
116
79
struct os_aio_slot_struct{
117
ibool is_read; /*!< TRUE if a read operation */
118
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
120
ibool reserved; /*!< TRUE if this slot is reserved */
121
time_t reservation_time;/*!< time when reserved */
122
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
124
byte* buf; /*!< buffer used in i/o */
125
ulint type; /*!< OS_FILE_READ or OS_FILE_WRITE */
126
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
128
ulint offset_high; /*!< 32 high bits of file offset */
129
os_file_t file; /*!< file where to read or write */
130
const char* name; /*!< file name or path */
131
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:
132
95
TRUE if the physical i/o already
133
96
made and only the slot message
134
97
needs to be passed to the caller
135
98
of os_aio_simulated_handle */
136
fil_node_t* message1; /*!< message which is given by the */
137
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
138
101
and which can be used to identify
139
102
which pending aio operation was
141
104
#ifdef WIN_ASYNC_IO
142
os_event_t event; /*!< event object we need in the
105
os_event_t event; /* event object we need in the
143
106
OVERLAPPED struct */
144
OVERLAPPED control; /*!< Windows control block for the
107
OVERLAPPED control; /* Windows control block for the
149
/** The asynchronous i/o array structure */
112
/* The aio array structure */
150
113
typedef struct os_aio_array_struct os_aio_array_t;
152
/** The asynchronous i/o array structure */
153
115
struct os_aio_array_struct{
154
os_mutex_t mutex; /*!< the mutex protecting the aio array */
156
/*!< The event which is set to the
157
signaled state when there is space in
158
the aio outside the ibuf segment */
160
/*!< The event which is set to the
161
signaled state when there are no
162
pending i/os in this array */
163
ulint n_slots;/*!< Total number of slots in the aio
164
array. This must be divisible by
167
/*!< Number of segments in the aio
168
array of pending aio requests. A
169
thread can wait separately for any one
172
/*!< Number of reserved slots in the
173
aio array outside the ibuf segment */
174
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
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 */
176
132
os_native_event_t* native_events;
177
/*!< Pointer to an array of OS native
178
event handles where we copied the
179
handles from slots, in the same
180
order. This can be used in
181
WaitForMultipleObjects; used only in
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
186
/** Array of events used in simulated aio */
141
/* Array of events used in simulated aio */
187
142
static os_event_t* os_aio_segment_wait_events = NULL;
189
/** The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These
190
are NULL when the module has not yet been initialized. @{ */
191
static os_aio_array_t* os_aio_read_array = NULL; /*!< Reads */
192
static os_aio_array_t* os_aio_write_array = NULL; /*!< Writes */
193
static os_aio_array_t* os_aio_ibuf_array = NULL; /*!< Insert buffer */
194
static os_aio_array_t* os_aio_log_array = NULL; /*!< Redo log */
195
static os_aio_array_t* os_aio_sync_array = NULL; /*!< Synchronous I/O */
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;
198
/** Number of asynchronous I/O segments. Set by os_aio_init(). */
199
152
static ulint os_aio_n_segments = ULINT_UNDEFINED;
201
/** 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
202
155
wait until a batch of new read requests have been posted */
203
156
static ibool os_aio_recommend_sleep_for_read_threads = FALSE;
204
#endif /* !UNIV_HOTBACKUP */
206
158
UNIV_INTERN ulint os_n_file_reads = 0;
207
159
UNIV_INTERN ulint os_bytes_read_since_printout = 0;
480
/****************************************************************//**
481
Does error handling when a file operation fails.
482
@return TRUE if we should retry the operation */
428
/********************************************************************
429
Does error handling when a file operation fails. */
485
432
os_file_handle_error(
486
433
/*=================*/
487
const char* name, /*!< in: name of a file or NULL */
488
const char* operation)/*!< in: operation */
434
/* out: TRUE if we should retry the
436
const char* name, /* in: name of a file or NULL */
437
const char* operation)/* in: operation */
490
439
/* exit in case of unknown error */
491
440
return(os_file_handle_error_cond_exit(name, operation, TRUE));
494
/****************************************************************//**
495
Does error handling when a file operation fails.
496
@return TRUE if we should retry the operation */
443
/********************************************************************
444
Does error handling when a file operation fails. */
499
447
os_file_handle_error_no_exit(
500
448
/*=========================*/
501
const char* name, /*!< in: name of a file or NULL */
502
const char* operation)/*!< in: operation */
449
/* out: TRUE if we should retry the
451
const char* name, /* in: name of a file or NULL */
452
const char* operation)/* in: operation */
504
454
/* don't exit in case of unknown error */
505
455
return(os_file_handle_error_cond_exit(name, operation, FALSE));
567
/***********************************************************************//**
516
/***************************************************************************
568
517
Creates a temporary file. This function is like tmpfile(3), but
569
518
the temporary file is created in the MySQL temporary directory.
570
519
On Netware, this function is like tmpfile(3), because the C run-time
571
library of Netware does not expose the delete-on-close flag.
572
@return temporary file handle, or NULL on error */
520
library of Netware does not expose the delete-on-close flag. */
575
523
os_file_create_tmpfile(void)
576
524
/*========================*/
525
/* out: temporary file handle, or NULL on error */
527
#ifdef UNIV_HOTBACKUP
579
533
FILE* file = tmpfile();
580
#else /* __NETWARE__ */
534
# else /* __NETWARE__ */
581
535
FILE* file = NULL;
582
536
int fd = innobase_mysql_tmpfile();
585
539
file = fdopen(fd, "w+b");
587
#endif /* __NETWARE__ */
541
# endif /* __NETWARE__ */
590
544
ut_print_timestamp(stderr);
592
546
" InnoDB: Error: unable to create temporary file;"
593
547
" errno: %d\n", errno);
598
#endif /* !__NETWARE__ */
552
# endif /* !__NETWARE__ */
556
#endif /* UNIV_HOTBACKUP */
603
#endif /* !UNIV_HOTBACKUP */
605
/***********************************************************************//**
559
/***************************************************************************
606
560
The os_file_opendir() function opens a directory stream corresponding to the
607
561
directory named by the dirname argument. The directory stream is positioned
608
562
at the first entry. In both Unix and Windows we automatically skip the '.'
609
and '..' items at the start of the directory listing.
610
@return directory stream, NULL if error */
563
and '..' items at the start of the directory listing. */
615
const char* dirname, /*!< in: directory name; it must not
568
/* out: directory stream, NULL if
570
const char* dirname, /* in: directory name; it must not
616
571
contain a trailing '\' or '/' */
617
ibool error_is_fatal) /*!< in: TRUE if we should treat an
572
ibool error_is_fatal) /* in: TRUE if we should treat an
618
573
error as a fatal error; if we try to
619
574
open symlinks then we do not wish a
620
575
fatal error if it happens not to be
893
/****************************************************************//**
894
A simple function to open or create a file.
895
@return own: handle to the file, not defined if error, error number
896
can be retrieved with os_file_get_last_error */
851
/********************************************************************
852
A simple function to open or create a file. */
899
855
os_file_create_simple(
900
856
/*==================*/
901
const char* name, /*!< in: name of the file or path as a
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
902
861
null-terminated string */
903
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
904
863
opened (if does not exist, error), or
905
864
OS_FILE_CREATE if a new file is created
906
865
(if exists, error), or
907
866
OS_FILE_CREATE_PATH if new file
908
867
(if exists, error) and subdirectories along
909
868
its path are created (if needed)*/
910
ulint access_type,/*!< in: OS_FILE_READ_ONLY or
869
ulint access_type,/* in: OS_FILE_READ_ONLY or
911
870
OS_FILE_READ_WRITE */
912
ibool* success)/*!< out: TRUE if succeed, FALSE if error */
871
ibool* success)/* out: TRUE if succeed, FALSE if error */
1031
990
#endif /* __WIN__ */
1034
/****************************************************************//**
1035
A simple function to open or create a file.
1036
@return own: handle to the file, not defined if error, error number
1037
can be retrieved with os_file_get_last_error */
993
/********************************************************************
994
A simple function to open or create a file. */
1040
997
os_file_create_simple_no_error_handling(
1041
998
/*====================================*/
1042
const char* name, /*!< in: name of the file or path as a
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
1043
1003
null-terminated string */
1044
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
1004
ulint create_mode,/* in: OS_FILE_OPEN if an existing file
1045
1005
is opened (if does not exist, error), or
1046
1006
OS_FILE_CREATE if a new file is created
1047
1007
(if exists, error) */
1048
ulint access_type,/*!< in: OS_FILE_READ_ONLY,
1008
ulint access_type,/* in: OS_FILE_READ_ONLY,
1049
1009
OS_FILE_READ_WRITE, or
1050
1010
OS_FILE_READ_ALLOW_DELETE; the last option is
1051
1011
used by a backup program reading the file */
1052
ibool* success)/*!< out: TRUE if succeed, FALSE if error */
1012
ibool* success)/* out: TRUE if succeed, FALSE if error */
1055
1015
os_file_t file;
2330
/*******************************************************************//**
2290
/***********************************************************************
2331
2291
Requests a synchronous positioned read operation. This function does not do
2332
any error handling. In case of error it returns FALSE.
2333
@return TRUE if request was successful, FALSE if fail */
2292
any error handling. In case of error it returns FALSE. */
2336
2295
os_file_read_no_error_handling(
2337
2296
/*===========================*/
2338
os_file_t file, /*!< in: handle to a file */
2339
void* buf, /*!< in: buffer where to read */
2340
ulint offset, /*!< in: least significant 32 bits of file
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
2341
2302
offset where to read */
2342
ulint offset_high, /*!< in: most significant 32 bits of
2303
ulint offset_high, /* in: most significant 32 bits of
2344
ulint n) /*!< in: number of bytes to read */
2305
ulint n) /* in: number of bytes to read */
2447
2408
str[flen] = '\0';
2450
/*******************************************************************//**
2451
Requests a synchronous write operation.
2452
@return TRUE if request was successful, FALSE if fail */
2411
/***********************************************************************
2412
Requests a synchronous write operation. */
2457
const char* name, /*!< in: name of the file or path as a
2417
/* out: TRUE if request was
2418
successful, FALSE if fail */
2419
const char* name, /* in: name of the file or path as a
2458
2420
null-terminated string */
2459
os_file_t file, /*!< in: handle to a file */
2460
const void* buf, /*!< in: buffer from which to write */
2461
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
2462
2424
offset where to write */
2463
ulint offset_high, /*!< in: most significant 32 bits of
2425
ulint offset_high, /* in: most significant 32 bits of
2465
ulint n) /*!< in: number of bytes to write */
2427
ulint n) /* in: number of bytes to write */
2888
2856
return(success);
2891
#ifndef UNIV_HOTBACKUP
2892
/****************************************************************//**
2893
Returns a pointer to the nth slot in the aio array.
2894
@return pointer to slot */
2859
/********************************************************************
2860
Returns a pointer to the nth slot in the aio array. */
2897
2863
os_aio_array_get_nth_slot(
2898
2864
/*======================*/
2899
os_aio_array_t* array, /*!< in: aio array */
2900
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 */
2902
2869
ut_a(index < array->n_slots);
2904
2871
return((array->slots) + index);
2907
/************************************************************************//**
2908
Creates an aio wait array.
2909
@return own: aio array */
2874
/****************************************************************************
2875
Creates an aio wait array. */
2911
2877
os_aio_array_t*
2912
2878
os_aio_array_create(
2913
2879
/*================*/
2914
ulint n, /*!< in: maximum number of pending aio operations
2880
/* out, own: aio array */
2881
ulint n, /* in: maximum number of pending aio operations
2915
2882
allowed; n must be divisible by n_segments */
2916
ulint n_segments) /*!< in: number of segments in the aio array */
2883
ulint n_segments) /* in: number of segments in the aio array */
2918
2885
os_aio_array_t* array;
2961
/***********************************************************************
2962
Initializes the asynchronous io system. Creates one array each for ibuf
2963
and log i/o. Also creates one array each for read and write where each
2964
array is divided logically into n_read_segs and n_write_segs
2965
respectively. The caller must create an i/o handler thread for each
2966
segment in these arrays. This function also creates the sync array.
2967
No i/o handler thread needs to be created for that */
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. */
2972
ulint n_per_seg, /*<! in: maximum number of pending aio
2973
operations allowed per segment */
2974
ulint n_read_segs, /*<! in: number of reader threads */
2975
ulint n_write_segs, /*<! in: number of writer threads */
2976
ulint n_slots_sync) /*<! in: number of slots in the sync aio
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 */
2980
ulint n_segments = 2 + n_read_segs + n_write_segs;
2952
ut_ad(n % n_segments == 0);
2982
2953
ut_ad(n_segments >= 4);
2984
2955
os_io_init_simple();
3155
3130
return(segment);
3158
/*******************************************************************//**
3133
/***********************************************************************
3159
3134
Requests for a slot in the aio array. If no slot is available, waits until
3160
not_full-event becomes signaled.
3161
@return pointer to slot */
3135
not_full-event becomes signaled. */
3164
3138
os_aio_array_reserve_slot(
3165
3139
/*======================*/
3166
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3167
os_aio_array_t* array, /*!< in: aio array */
3168
fil_node_t* message1,/*!< in: message to be passed along with
3169
the aio operation */
3170
void* message2,/*!< in: message to be passed along with
3171
the aio operation */
3172
os_file_t file, /*!< in: file handle */
3173
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
3174
3149
null-terminated string */
3175
void* buf, /*!< in: buffer where to read or from which
3150
void* buf, /* in: buffer where to read or from which
3177
ulint offset, /*!< in: least significant 32 bits of file
3179
ulint offset_high, /*!< in: most significant 32 bits of
3181
ulint len) /*!< in: length of the block to read or write */
3152
ulint offset, /* in: least significant 32 bits of file
3154
ulint offset_high, /* in: most significant 32 bits of
3156
ulint len) /* in: length of the block to read or write */
3183
3158
os_aio_slot_t* slot;
3184
3159
#ifdef WIN_ASYNC_IO
3185
3160
OVERLAPPED* control;
3188
ulint slots_per_seg;
3191
/* No need of a mutex. Only reading constant fields */
3192
slots_per_seg = array->n_slots / array->n_segments;
3194
/* We attempt to keep adjacent blocks in the same local
3195
segment. This can help in merging IO requests when we are
3196
doing simulated AIO */
3197
local_seg = (offset >> (UNIV_PAGE_SIZE_SHIFT + 6))
3198
% array->n_segments;
3201
3164
os_mutex_enter(array->mutex);
3414
3366
because i/os are not actually handled until
3415
3367
all have been posted: use with great
3417
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
3418
3370
null-terminated string */
3419
os_file_t file, /*!< in: handle to a file */
3420
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
3422
ulint offset, /*!< in: least significant 32 bits of file
3374
ulint offset, /* in: least significant 32 bits of file
3423
3375
offset where to read or write */
3424
ulint offset_high, /*!< in: most significant 32 bits of
3376
ulint offset_high, /* in: most significant 32 bits of
3426
ulint n, /*!< in: number of bytes to read or write */
3427
fil_node_t* message1,/*!< in: message for the aio handler
3428
(can be used to identify a completed
3429
aio operation); ignored if mode is
3431
void* message2)/*!< in: message for the aio handler
3432
(can be used to identify a completed
3433
aio operation); ignored if mode is
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
3436
3385
os_aio_array_t* array;
3437
3386
os_aio_slot_t* slot;
3695
/**********************************************************************//**
3644
/**************************************************************************
3696
3645
Does simulated aio. This function should be called by an i/o-handler
3698
@return TRUE if the aio operation succeeded */
3701
3649
os_aio_simulated_handle(
3702
3650
/*====================*/
3703
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
3704
3653
arrays to wait for; segment 0 is the ibuf
3705
3654
i/o thread, segment 1 the log i/o thread,
3706
3655
then follow the non-ibuf read threads, and as
3707
3656
the last are the non-ibuf write threads */
3708
fil_node_t**message1, /*!< out: the messages passed with the aio
3657
fil_node_t**message1, /* out: the messages passed with the aio
3709
3658
request; note that also in the case where
3710
3659
the aio operation failed, these output
3711
3660
parameters are valid and can be used to
3712
3661
restart the operation, for example */
3713
3662
void** message2,
3714
ulint* type) /*!< out: OS_FILE_WRITE or ..._READ */
3663
ulint* type) /* out: OS_FILE_WRITE or ..._READ */
3716
3665
os_aio_array_t* array;