~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2008-10-06 06:47:29 UTC
  • Revision ID: brian@tangent.org-20081006064729-2i9mhjkzyvow9xsm
RemoveĀ uint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
4
 
 
5
 
This program is free software; you can redistribute it and/or modify it under
6
 
the terms of the GNU General Public License as published by the Free Software
7
 
Foundation; version 2 of the License.
8
 
 
9
 
This program is distributed in the hope that it will be useful, but WITHOUT
10
 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
 
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
 
 
13
 
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
 
Place, Suite 330, Boston, MA 02111-1307 USA
16
 
 
17
 
*****************************************************************************/
18
 
/***********************************************************************
19
 
 
20
 
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
21
 
Copyright (c) 2009, Percona Inc.
22
 
 
23
 
Portions of this file contain modifications contributed and copyrighted
24
 
by Percona Inc.. Those modifications are
25
 
gratefully acknowledged and are described briefly in the InnoDB
26
 
documentation. The contributions by Percona Inc. are incorporated with
27
 
their permission, and subject to the conditions contained in the file
28
 
COPYING.Percona.
29
 
 
30
 
This program is free software; you can redistribute it and/or modify it
31
 
under the terms of the GNU General Public License as published by the
32
 
Free Software Foundation; version 2 of the License.
33
 
 
34
 
This program is distributed in the hope that it will be useful, but
35
 
WITHOUT ANY WARRANTY; without even the implied warranty of
36
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
37
 
Public License for more details.
38
 
 
39
 
You should have received a copy of the GNU General Public License along
40
 
with this program; if not, write to the Free Software Foundation, Inc.,
41
 
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42
 
 
43
 
***********************************************************************/
44
 
 
45
 
/**************************************************//**
46
 
@file os/os0file.c
47
 
The interface to the operating system file i/o primitives
48
 
 
49
 
Created 10/21/1995 Heikki Tuuri
50
 
*******************************************************/
51
 
 
52
 
#include "os0file.h"
53
 
#include "ut0mem.h"
54
 
#include "srv0srv.h"
55
 
#include "srv0start.h"
56
 
#include "fil0fil.h"
57
 
#include "buf0buf.h"
58
 
#include <errno.h>
59
 
#include <fcntl.h>
60
 
#include <limits.h>
61
 
#include <unistd.h>
62
 
#ifndef UNIV_HOTBACKUP
63
 
# include "os0sync.h"
64
 
# include "os0thread.h"
65
 
#else /* !UNIV_HOTBACKUP */
66
 
# ifdef __WIN__
67
 
/* Add includes for the _stat() call to compile on Windows */
68
 
#  include <sys/types.h>
69
 
#  include <sys/stat.h>
70
 
# endif /* __WIN__ */
71
 
#endif /* !UNIV_HOTBACKUP */
72
 
 
73
 
/* This specifies the file permissions InnoDB uses when it creates files in
74
 
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
75
 
my_umask */
76
 
 
77
 
#ifndef __WIN__
78
 
/** Umask for creating files */
79
 
UNIV_INTERN ulint       os_innodb_umask
80
 
                        = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
81
 
#else
82
 
/** Umask for creating files */
83
 
UNIV_INTERN ulint       os_innodb_umask         = 0;
84
 
#endif
85
 
 
86
 
#ifdef UNIV_DO_FLUSH
87
 
/* If the following is set to TRUE, we do not call os_file_flush in every
88
 
os_file_write. We can set this TRUE when the doublewrite buffer is used. */
89
 
UNIV_INTERN ibool       os_do_not_call_flush_at_each_write      = FALSE;
90
 
#else
91
 
/* We do not call os_file_flush in every os_file_write. */
92
 
#endif /* UNIV_DO_FLUSH */
93
 
 
94
 
#ifndef UNIV_HOTBACKUP
95
 
/* We use these mutexes to protect lseek + file i/o operation, if the
96
 
OS does not provide an atomic pread or pwrite, or similar */
97
 
#define OS_FILE_N_SEEK_MUTEXES  16
98
 
UNIV_INTERN os_mutex_t  os_file_seek_mutexes[OS_FILE_N_SEEK_MUTEXES];
99
 
 
100
 
/* In simulated aio, merge at most this many consecutive i/os */
101
 
#define OS_AIO_MERGE_N_CONSECUTIVE      64
102
 
 
103
 
/** If this flag is TRUE, then we will use the native aio of the
104
 
OS (provided we compiled Innobase with it in), otherwise we will
105
 
use simulated aio we build below with threads */
106
 
 
107
 
UNIV_INTERN ibool       os_aio_use_native_aio   = FALSE;
108
 
 
109
 
/** Flag: enable debug printout for asynchronous i/o */
110
 
UNIV_INTERN ibool       os_aio_print_debug      = FALSE;
111
 
 
112
 
/** The asynchronous i/o array slot structure */
113
 
typedef struct os_aio_slot_struct       os_aio_slot_t;
114
 
 
115
 
/** The asynchronous i/o array slot structure */
116
 
struct os_aio_slot_struct{
117
 
        ibool           is_read;        /*!< TRUE if a read operation */
118
 
        ulint           pos;            /*!< index of the slot in the aio
119
 
                                        array */
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
123
 
                                        write */
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
127
 
                                        bytes */
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:
132
 
                                        TRUE if the physical i/o already
133
 
                                        made and only the slot message
134
 
                                        needs to be passed to the caller
135
 
                                        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
138
 
                                        and which can be used to identify
139
 
                                        which pending aio operation was
140
 
                                        completed */
141
 
#ifdef WIN_ASYNC_IO
142
 
        os_event_t      event;          /*!< event object we need in the
143
 
                                        OVERLAPPED struct */
144
 
        OVERLAPPED      control;        /*!< Windows control block for the
145
 
                                        aio request */
146
 
#endif
147
 
};
148
 
 
149
 
/** The asynchronous i/o array structure */
150
 
typedef struct os_aio_array_struct      os_aio_array_t;
151
 
 
152
 
/** The asynchronous i/o array structure */
153
 
struct os_aio_array_struct{
154
 
        os_mutex_t      mutex;  /*!< the mutex protecting the aio array */
155
 
        os_event_t      not_full;
156
 
                                /*!< The event which is set to the
157
 
                                signaled state when there is space in
158
 
                                the aio outside the ibuf segment */
159
 
        os_event_t      is_empty;
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
165
 
                                n_threads. */
166
 
        ulint           n_segments;
167
 
                                /*!< Number of segments in the aio
168
 
                                array of pending aio requests. A
169
 
                                thread can wait separately for any one
170
 
                                of the segments. */
171
 
        ulint           n_reserved;
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 */
175
 
#ifdef __WIN__
176
 
        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
182
 
                                Windows */
183
 
#endif
184
 
};
185
 
 
186
 
/** Array of events used in simulated aio */
187
 
static os_event_t*      os_aio_segment_wait_events      = NULL;
188
 
 
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 */
196
 
/* @} */
197
 
 
198
 
/** Number of asynchronous I/O segments.  Set by os_aio_init(). */
199
 
static ulint    os_aio_n_segments       = ULINT_UNDEFINED;
200
 
 
201
 
/** If the following is TRUE, read i/o handler threads try to
202
 
wait until a batch of new read requests have been posted */
203
 
static ibool    os_aio_recommend_sleep_for_read_threads = FALSE;
204
 
#endif /* !UNIV_HOTBACKUP */
205
 
 
206
 
UNIV_INTERN ulint       os_n_file_reads         = 0;
207
 
UNIV_INTERN ulint       os_bytes_read_since_printout = 0;
208
 
UNIV_INTERN ulint       os_n_file_writes        = 0;
209
 
UNIV_INTERN ulint       os_n_fsyncs             = 0;
210
 
UNIV_INTERN ulint       os_n_file_reads_old     = 0;
211
 
UNIV_INTERN ulint       os_n_file_writes_old    = 0;
212
 
UNIV_INTERN ulint       os_n_fsyncs_old         = 0;
213
 
UNIV_INTERN time_t      os_last_printout;
214
 
 
215
 
UNIV_INTERN ibool       os_has_said_disk_full   = FALSE;
216
 
 
217
 
#ifndef UNIV_HOTBACKUP
218
 
/** The mutex protecting the following counts of pending I/O operations */
219
 
static os_mutex_t       os_file_count_mutex;
220
 
#endif /* !UNIV_HOTBACKUP */
221
 
/** Number of pending os_file_pread() operations */
222
 
UNIV_INTERN ulint       os_file_n_pending_preads  = 0;
223
 
/** Number of pending os_file_pwrite() operations */
224
 
UNIV_INTERN ulint       os_file_n_pending_pwrites = 0;
225
 
/** Number of pending write operations */
226
 
UNIV_INTERN ulint       os_n_pending_writes = 0;
227
 
/** Number of pending read operations */
228
 
UNIV_INTERN ulint       os_n_pending_reads = 0;
229
 
 
230
 
/***********************************************************************//**
231
 
Gets the operating system version. Currently works only on Windows.
232
 
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */
233
 
UNIV_INTERN
234
 
ulint
235
 
os_get_os_version(void)
236
 
/*===================*/
237
 
{
238
 
#ifdef __WIN__
239
 
        OSVERSIONINFO     os_info;
240
 
 
241
 
        os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
242
 
 
243
 
        ut_a(GetVersionEx(&os_info));
244
 
 
245
 
        if (os_info.dwPlatformId == VER_PLATFORM_WIN32s) {
246
 
                return(OS_WIN31);
247
 
        } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
248
 
                return(OS_WIN95);
249
 
        } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
250
 
                if (os_info.dwMajorVersion <= 4) {
251
 
                        return(OS_WINNT);
252
 
                } else {
253
 
                        return(OS_WIN2000);
254
 
                }
255
 
        } else {
256
 
                ut_error;
257
 
                return(0);
258
 
        }
259
 
#else
260
 
        ut_error;
261
 
 
262
 
        return(0);
263
 
#endif
264
 
}
265
 
 
266
 
/***********************************************************************//**
267
 
Retrieves the last error number if an error occurs in a file io function.
268
 
The number should be retrieved before any other OS calls (because they may
269
 
overwrite the error number). If the number is not known to this program,
270
 
the OS error number + 100 is returned.
271
 
@return error number, or OS error number + 100 */
272
 
UNIV_INTERN
273
 
ulint
274
 
os_file_get_last_error(
275
 
/*===================*/
276
 
        ibool   report_all_errors)      /*!< in: TRUE if we want an error message
277
 
                                        printed of all errors */
278
 
{
279
 
        ulint   err;
280
 
 
281
 
#ifdef __WIN__
282
 
 
283
 
        err = (ulint) GetLastError();
284
 
 
285
 
        if (report_all_errors
286
 
            || (err != ERROR_DISK_FULL && err != ERROR_FILE_EXISTS)) {
287
 
 
288
 
                ut_print_timestamp(stderr);
289
 
                fprintf(stderr,
290
 
                        "  InnoDB: Operating system error number %lu"
291
 
                        " in a file operation.\n", (ulong) err);
292
 
 
293
 
                if (err == ERROR_PATH_NOT_FOUND) {
294
 
                        fprintf(stderr,
295
 
                                "InnoDB: The error means the system"
296
 
                                " cannot find the path specified.\n");
297
 
 
298
 
                        if (srv_is_being_started) {
299
 
                                fprintf(stderr,
300
 
                                        "InnoDB: If you are installing InnoDB,"
301
 
                                        " remember that you must create\n"
302
 
                                        "InnoDB: directories yourself, InnoDB"
303
 
                                        " does not create them.\n");
304
 
                        }
305
 
                } else if (err == ERROR_ACCESS_DENIED) {
306
 
                        fprintf(stderr,
307
 
                                "InnoDB: The error means mysqld does not have"
308
 
                                " the access rights to\n"
309
 
                                "InnoDB: the directory. It may also be"
310
 
                                " you have created a subdirectory\n"
311
 
                                "InnoDB: of the same name as a data file.\n");
312
 
                } else if (err == ERROR_SHARING_VIOLATION
313
 
                           || err == ERROR_LOCK_VIOLATION) {
314
 
                        fprintf(stderr,
315
 
                                "InnoDB: The error means that another program"
316
 
                                " is using InnoDB's files.\n"
317
 
                                "InnoDB: This might be a backup or antivirus"
318
 
                                " software or another instance\n"
319
 
                                "InnoDB: of MySQL."
320
 
                                " Please close it to get rid of this error.\n");
321
 
                } else {
322
 
                        fprintf(stderr,
323
 
                                "InnoDB: Some operating system error numbers"
324
 
                                " are described at\n"
325
 
                                "InnoDB: "
326
 
                                REFMAN
327
 
                                "operating-system-error-codes.html\n");
328
 
                }
329
 
        }
330
 
 
331
 
        fflush(stderr);
332
 
 
333
 
        if (err == ERROR_FILE_NOT_FOUND) {
334
 
                return(OS_FILE_NOT_FOUND);
335
 
        } else if (err == ERROR_DISK_FULL) {
336
 
                return(OS_FILE_DISK_FULL);
337
 
        } else if (err == ERROR_FILE_EXISTS) {
338
 
                return(OS_FILE_ALREADY_EXISTS);
339
 
        } else if (err == ERROR_SHARING_VIOLATION
340
 
                   || err == ERROR_LOCK_VIOLATION) {
341
 
                return(OS_FILE_SHARING_VIOLATION);
342
 
        } else {
343
 
                return(100 + err);
344
 
        }
345
 
#else
346
 
        err = (ulint) errno;
347
 
 
348
 
        if (report_all_errors
349
 
            || (err != ENOSPC && err != EEXIST)) {
350
 
 
351
 
                ut_print_timestamp(stderr);
352
 
                fprintf(stderr,
353
 
                        "  InnoDB: Operating system error number %lu"
354
 
                        " in a file operation.\n", (ulong) err);
355
 
 
356
 
                if (err == ENOENT) {
357
 
                        fprintf(stderr,
358
 
                                "InnoDB: The error means the system"
359
 
                                " cannot find the path specified.\n");
360
 
 
361
 
                        if (srv_is_being_started) {
362
 
                                fprintf(stderr,
363
 
                                        "InnoDB: If you are installing InnoDB,"
364
 
                                        " remember that you must create\n"
365
 
                                        "InnoDB: directories yourself, InnoDB"
366
 
                                        " does not create them.\n");
367
 
                        }
368
 
                } else if (err == EACCES) {
369
 
                        fprintf(stderr,
370
 
                                "InnoDB: The error means mysqld does not have"
371
 
                                " the access rights to\n"
372
 
                                "InnoDB: the directory.\n");
373
 
                } else {
374
 
                        if (strerror((int)err) != NULL) {
375
 
                                fprintf(stderr,
376
 
                                        "InnoDB: Error number %lu"
377
 
                                        " means '%s'.\n",
378
 
                                        err, strerror((int)err));
379
 
                        }
380
 
 
381
 
                        fprintf(stderr,
382
 
                                "InnoDB: Some operating system"
383
 
                                " error numbers are described at\n"
384
 
                                "InnoDB: "
385
 
                                REFMAN
386
 
                                "operating-system-error-codes.html\n");
387
 
                }
388
 
        }
389
 
 
390
 
        fflush(stderr);
391
 
 
392
 
        if (err == ENOSPC) {
393
 
                return(OS_FILE_DISK_FULL);
394
 
        } else if (err == ENOENT) {
395
 
                return(OS_FILE_NOT_FOUND);
396
 
        } else if (err == EEXIST) {
397
 
                return(OS_FILE_ALREADY_EXISTS);
398
 
        } else if (err == EXDEV || err == ENOTDIR || err == EISDIR) {
399
 
                return(OS_FILE_PATH_ERROR);
400
 
        } else {
401
 
                return(100 + err);
402
 
        }
403
 
#endif
404
 
}
405
 
 
406
 
/****************************************************************//**
407
 
Does error handling when a file operation fails.
408
 
Conditionally exits (calling exit(3)) based on should_exit value and the
409
 
error type
410
 
@return TRUE if we should retry the operation */
411
 
static
412
 
ibool
413
 
os_file_handle_error_cond_exit(
414
 
/*===========================*/
415
 
        const char*     name,           /*!< in: name of a file or NULL */
416
 
        const char*     operation,      /*!< in: operation */
417
 
        ibool           should_exit)    /*!< in: call exit(3) if unknown error
418
 
                                        and this parameter is TRUE */
419
 
{
420
 
        ulint   err;
421
 
 
422
 
        err = os_file_get_last_error(FALSE);
423
 
 
424
 
        if (err == OS_FILE_DISK_FULL) {
425
 
                /* We only print a warning about disk full once */
426
 
 
427
 
                if (os_has_said_disk_full) {
428
 
 
429
 
                        return(FALSE);
430
 
                }
431
 
 
432
 
                if (name) {
433
 
                        ut_print_timestamp(stderr);
434
 
                        fprintf(stderr,
435
 
                                "  InnoDB: Encountered a problem with"
436
 
                                " file %s\n", name);
437
 
                }
438
 
 
439
 
                ut_print_timestamp(stderr);
440
 
                fprintf(stderr,
441
 
                        "  InnoDB: Disk is full. Try to clean the disk"
442
 
                        " to free space.\n");
443
 
 
444
 
                os_has_said_disk_full = TRUE;
445
 
 
446
 
                fflush(stderr);
447
 
 
448
 
                return(FALSE);
449
 
        } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
450
 
 
451
 
                return(TRUE);
452
 
        } else if (err == OS_FILE_ALREADY_EXISTS
453
 
                   || err == OS_FILE_PATH_ERROR) {
454
 
 
455
 
                return(FALSE);
456
 
        } else if (err == OS_FILE_SHARING_VIOLATION) {
457
 
 
458
 
                os_thread_sleep(10000000);  /* 10 sec */
459
 
                return(TRUE);
460
 
        } else {
461
 
                if (name) {
462
 
                        fprintf(stderr, "InnoDB: File name %s\n", name);
463
 
                }
464
 
 
465
 
                fprintf(stderr, "InnoDB: File operation call: '%s'.\n",
466
 
                        operation);
467
 
 
468
 
                if (should_exit) {
469
 
                        fprintf(stderr, "InnoDB: Cannot continue operation.\n");
470
 
 
471
 
                        fflush(stderr);
472
 
 
473
 
                        exit(1);
474
 
                }
475
 
        }
476
 
 
477
 
        return(FALSE);
478
 
}
479
 
 
480
 
/****************************************************************//**
481
 
Does error handling when a file operation fails.
482
 
@return TRUE if we should retry the operation */
483
 
static
484
 
ibool
485
 
os_file_handle_error(
486
 
/*=================*/
487
 
        const char*     name,   /*!< in: name of a file or NULL */
488
 
        const char*     operation)/*!< in: operation */
489
 
{
490
 
        /* exit in case of unknown error */
491
 
        return(os_file_handle_error_cond_exit(name, operation, TRUE));
492
 
}
493
 
 
494
 
/****************************************************************//**
495
 
Does error handling when a file operation fails.
496
 
@return TRUE if we should retry the operation */
497
 
static
498
 
ibool
499
 
os_file_handle_error_no_exit(
500
 
/*=========================*/
501
 
        const char*     name,   /*!< in: name of a file or NULL */
502
 
        const char*     operation)/*!< in: operation */
503
 
{
504
 
        /* don't exit in case of unknown error */
505
 
        return(os_file_handle_error_cond_exit(name, operation, FALSE));
506
 
}
507
 
 
508
 
#undef USE_FILE_LOCK
509
 
#define USE_FILE_LOCK
510
 
#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__NETWARE__)
511
 
/* InnoDB Hot Backup does not lock the data files.
512
 
 * On Windows, mandatory locking is used.
513
 
 */
514
 
# undef USE_FILE_LOCK
515
 
#endif
516
 
#ifdef USE_FILE_LOCK
517
 
/****************************************************************//**
518
 
Obtain an exclusive lock on a file.
519
 
@return 0 on success */
520
 
static
521
 
int
522
 
os_file_lock(
523
 
/*=========*/
524
 
        int             fd,     /*!< in: file descriptor */
525
 
        const char*     name)   /*!< in: file name */
526
 
{
527
 
        struct flock lk;
528
 
        lk.l_type = F_WRLCK;
529
 
        lk.l_whence = SEEK_SET;
530
 
        lk.l_start = lk.l_len = 0;
531
 
        if (fcntl(fd, F_SETLK, &lk) == -1) {
532
 
                fprintf(stderr,
533
 
                        "InnoDB: Unable to lock %s, error: %d\n", name, errno);
534
 
 
535
 
                if (errno == EAGAIN || errno == EACCES) {
536
 
                        fprintf(stderr,
537
 
                                "InnoDB: Check that you do not already have"
538
 
                                " another mysqld process\n"
539
 
                                "InnoDB: using the same InnoDB data"
540
 
                                " or log files.\n");
541
 
                }
542
 
 
543
 
                return(-1);
544
 
        }
545
 
 
546
 
        return(0);
547
 
}
548
 
#endif /* USE_FILE_LOCK */
549
 
 
550
 
#ifndef UNIV_HOTBACKUP
551
 
/****************************************************************//**
552
 
Creates the seek mutexes used in positioned reads and writes. */
553
 
UNIV_INTERN
554
 
void
555
 
os_io_init_simple(void)
556
 
/*===================*/
557
 
{
558
 
        ulint   i;
559
 
 
560
 
        os_file_count_mutex = os_mutex_create(NULL);
561
 
 
562
 
        for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
563
 
                os_file_seek_mutexes[i] = os_mutex_create(NULL);
564
 
        }
565
 
}
566
 
 
567
 
/***********************************************************************//**
568
 
Creates a temporary file.  This function is like tmpfile(3), but
569
 
the temporary file is created in the MySQL temporary directory.
570
 
On Netware, this function is like tmpfile(3), because the C run-time
571
 
library of Netware does not expose the delete-on-close flag.
572
 
@return temporary file handle, or NULL on error */
573
 
UNIV_INTERN
574
 
FILE*
575
 
os_file_create_tmpfile(void)
576
 
/*========================*/
577
 
{
578
 
#ifdef __NETWARE__
579
 
        FILE*   file    = tmpfile();
580
 
#else /* __NETWARE__ */
581
 
        FILE*   file    = NULL;
582
 
        int     fd      = innobase_mysql_tmpfile();
583
 
 
584
 
        if (fd >= 0) {
585
 
                file = fdopen(fd, "w+b");
586
 
        }
587
 
#endif /* __NETWARE__ */
588
 
 
589
 
        if (!file) {
590
 
                ut_print_timestamp(stderr);
591
 
                fprintf(stderr,
592
 
                        "  InnoDB: Error: unable to create temporary file;"
593
 
                        " errno: %d\n", errno);
594
 
#ifndef __NETWARE__
595
 
                if (fd >= 0) {
596
 
                        close(fd);
597
 
                }
598
 
#endif /* !__NETWARE__ */
599
 
        }
600
 
 
601
 
        return(file);
602
 
}
603
 
#endif /* !UNIV_HOTBACKUP */
604
 
 
605
 
/***********************************************************************//**
606
 
The os_file_opendir() function opens a directory stream corresponding to the
607
 
directory named by the dirname argument. The directory stream is positioned
608
 
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 */
611
 
UNIV_INTERN
612
 
os_file_dir_t
613
 
os_file_opendir(
614
 
/*============*/
615
 
        const char*     dirname,        /*!< in: directory name; it must not
616
 
                                        contain a trailing '\' or '/' */
617
 
        ibool           error_is_fatal) /*!< in: TRUE if we should treat an
618
 
                                        error as a fatal error; if we try to
619
 
                                        open symlinks then we do not wish a
620
 
                                        fatal error if it happens not to be
621
 
                                        a directory */
622
 
{
623
 
        os_file_dir_t           dir;
624
 
#ifdef __WIN__
625
 
        LPWIN32_FIND_DATA       lpFindFileData;
626
 
        char                    path[OS_FILE_MAX_PATH + 3];
627
 
 
628
 
        ut_a(strlen(dirname) < OS_FILE_MAX_PATH);
629
 
 
630
 
        strcpy(path, dirname);
631
 
        strcpy(path + strlen(path), "\\*");
632
 
 
633
 
        /* Note that in Windows opening the 'directory stream' also retrieves
634
 
        the first entry in the directory. Since it is '.', that is no problem,
635
 
        as we will skip over the '.' and '..' entries anyway. */
636
 
 
637
 
        lpFindFileData = ut_malloc(sizeof(WIN32_FIND_DATA));
638
 
 
639
 
        dir = FindFirstFile((LPCTSTR) path, lpFindFileData);
640
 
 
641
 
        ut_free(lpFindFileData);
642
 
 
643
 
        if (dir == INVALID_HANDLE_VALUE) {
644
 
 
645
 
                if (error_is_fatal) {
646
 
                        os_file_handle_error(dirname, "opendir");
647
 
                }
648
 
 
649
 
                return(NULL);
650
 
        }
651
 
 
652
 
        return(dir);
653
 
#else
654
 
        dir = opendir(dirname);
655
 
 
656
 
        if (dir == NULL && error_is_fatal) {
657
 
                os_file_handle_error(dirname, "opendir");
658
 
        }
659
 
 
660
 
        return(dir);
661
 
#endif
662
 
}
663
 
 
664
 
/***********************************************************************//**
665
 
Closes a directory stream.
666
 
@return 0 if success, -1 if failure */
667
 
UNIV_INTERN
668
 
int
669
 
os_file_closedir(
670
 
/*=============*/
671
 
        os_file_dir_t   dir)    /*!< in: directory stream */
672
 
{
673
 
#ifdef __WIN__
674
 
        BOOL            ret;
675
 
 
676
 
        ret = FindClose(dir);
677
 
 
678
 
        if (!ret) {
679
 
                os_file_handle_error_no_exit(NULL, "closedir");
680
 
 
681
 
                return(-1);
682
 
        }
683
 
 
684
 
        return(0);
685
 
#else
686
 
        int     ret;
687
 
 
688
 
        ret = closedir(dir);
689
 
 
690
 
        if (ret) {
691
 
                os_file_handle_error_no_exit(NULL, "closedir");
692
 
        }
693
 
 
694
 
        return(ret);
695
 
#endif
696
 
}
697
 
 
698
 
/***********************************************************************//**
699
 
This function returns information of the next file in the directory. We jump
700
 
over the '.' and '..' entries in the directory.
701
 
@return 0 if ok, -1 if error, 1 if at the end of the directory */
702
 
UNIV_INTERN
703
 
int
704
 
os_file_readdir_next_file(
705
 
/*======================*/
706
 
        const char*     dirname,/*!< in: directory name or path */
707
 
        os_file_dir_t   dir,    /*!< in: directory stream */
708
 
        os_file_stat_t* info)   /*!< in/out: buffer where the info is returned */
709
 
{
710
 
#ifdef __WIN__
711
 
        LPWIN32_FIND_DATA       lpFindFileData;
712
 
        BOOL                    ret;
713
 
 
714
 
        lpFindFileData = ut_malloc(sizeof(WIN32_FIND_DATA));
715
 
next_file:
716
 
        ret = FindNextFile(dir, lpFindFileData);
717
 
 
718
 
        if (ret) {
719
 
                ut_a(strlen((char *) lpFindFileData->cFileName)
720
 
                     < OS_FILE_MAX_PATH);
721
 
 
722
 
                if (strcmp((char *) lpFindFileData->cFileName, ".") == 0
723
 
                    || strcmp((char *) lpFindFileData->cFileName, "..") == 0) {
724
 
 
725
 
                        goto next_file;
726
 
                }
727
 
 
728
 
                strcpy(info->name, (char *) lpFindFileData->cFileName);
729
 
 
730
 
                info->size = (ib_int64_t)(lpFindFileData->nFileSizeLow)
731
 
                        + (((ib_int64_t)(lpFindFileData->nFileSizeHigh))
732
 
                           << 32);
733
 
 
734
 
                if (lpFindFileData->dwFileAttributes
735
 
                    & FILE_ATTRIBUTE_REPARSE_POINT) {
736
 
                        /* TODO: test Windows symlinks */
737
 
                        /* TODO: MySQL has apparently its own symlink
738
 
                        implementation in Windows, dbname.sym can
739
 
                        redirect a database directory:
740
 
                        REFMAN "windows-symbolic-links.html" */
741
 
                        info->type = OS_FILE_TYPE_LINK;
742
 
                } else if (lpFindFileData->dwFileAttributes
743
 
                           & FILE_ATTRIBUTE_DIRECTORY) {
744
 
                        info->type = OS_FILE_TYPE_DIR;
745
 
                } else {
746
 
                        /* It is probably safest to assume that all other
747
 
                        file types are normal. Better to check them rather
748
 
                        than blindly skip them. */
749
 
 
750
 
                        info->type = OS_FILE_TYPE_FILE;
751
 
                }
752
 
        }
753
 
 
754
 
        ut_free(lpFindFileData);
755
 
 
756
 
        if (ret) {
757
 
                return(0);
758
 
        } else if (GetLastError() == ERROR_NO_MORE_FILES) {
759
 
 
760
 
                return(1);
761
 
        } else {
762
 
                os_file_handle_error_no_exit(dirname,
763
 
                                             "readdir_next_file");
764
 
                return(-1);
765
 
        }
766
 
#else
767
 
        struct dirent*  ent;
768
 
        char*           full_path;
769
 
        int             ret;
770
 
        struct stat     statinfo;
771
 
#ifdef HAVE_READDIR_R
772
 
        char            dirent_buf[sizeof(struct dirent)
773
 
                                   + _POSIX_PATH_MAX + 100];
774
 
        /* In /mysys/my_lib.c, _POSIX_PATH_MAX + 1 is used as
775
 
        the max file name len; but in most standards, the
776
 
        length is NAME_MAX; we add 100 to be even safer */
777
 
#endif
778
 
 
779
 
next_file:
780
 
 
781
 
#ifdef HAVE_READDIR_R
782
 
        ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
783
 
 
784
 
        if (ret != 0) {
785
 
                fprintf(stderr,
786
 
                        "InnoDB: cannot read directory %s, error %lu\n",
787
 
                        dirname, (ulong)ret);
788
 
 
789
 
                return(-1);
790
 
        }
791
 
 
792
 
        if (ent == NULL) {
793
 
                /* End of directory */
794
 
 
795
 
                return(1);
796
 
        }
797
 
 
798
 
        ut_a(strlen(ent->d_name) < _POSIX_PATH_MAX + 100 - 1);
799
 
#else
800
 
        ent = readdir(dir);
801
 
 
802
 
        if (ent == NULL) {
803
 
 
804
 
                return(1);
805
 
        }
806
 
#endif
807
 
        ut_a(strlen(ent->d_name) < OS_FILE_MAX_PATH);
808
 
 
809
 
        if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
810
 
 
811
 
                goto next_file;
812
 
        }
813
 
 
814
 
        strcpy(info->name, ent->d_name);
815
 
 
816
 
        full_path = ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10);
817
 
 
818
 
        sprintf(full_path, "%s/%s", dirname, ent->d_name);
819
 
 
820
 
        ret = stat(full_path, &statinfo);
821
 
 
822
 
        if (ret) {
823
 
                os_file_handle_error_no_exit(full_path, "stat");
824
 
 
825
 
                ut_free(full_path);
826
 
 
827
 
                return(-1);
828
 
        }
829
 
 
830
 
        info->size = (ib_int64_t)statinfo.st_size;
831
 
 
832
 
        if (S_ISDIR(statinfo.st_mode)) {
833
 
                info->type = OS_FILE_TYPE_DIR;
834
 
        } else if (S_ISLNK(statinfo.st_mode)) {
835
 
                info->type = OS_FILE_TYPE_LINK;
836
 
        } else if (S_ISREG(statinfo.st_mode)) {
837
 
                info->type = OS_FILE_TYPE_FILE;
838
 
        } else {
839
 
                info->type = OS_FILE_TYPE_UNKNOWN;
840
 
        }
841
 
 
842
 
        ut_free(full_path);
843
 
 
844
 
        return(0);
845
 
#endif
846
 
}
847
 
 
848
 
/*****************************************************************//**
849
 
This function attempts to create a directory named pathname. The new directory
850
 
gets default permissions. On Unix the permissions are (0770 & ~umask). If the
851
 
directory exists already, nothing is done and the call succeeds, unless the
852
 
fail_if_exists arguments is true.
853
 
@return TRUE if call succeeds, FALSE on error */
854
 
UNIV_INTERN
855
 
ibool
856
 
os_file_create_directory(
857
 
/*=====================*/
858
 
        const char*     pathname,       /*!< in: directory name as
859
 
                                        null-terminated string */
860
 
        ibool           fail_if_exists) /*!< in: if TRUE, pre-existing directory
861
 
                                        is treated as an error. */
862
 
{
863
 
#ifdef __WIN__
864
 
        BOOL    rcode;
865
 
 
866
 
        rcode = CreateDirectory((LPCTSTR) pathname, NULL);
867
 
        if (!(rcode != 0
868
 
              || (GetLastError() == ERROR_ALREADY_EXISTS
869
 
                  && !fail_if_exists))) {
870
 
                /* failure */
871
 
                os_file_handle_error(pathname, "CreateDirectory");
872
 
 
873
 
                return(FALSE);
874
 
        }
875
 
 
876
 
        return (TRUE);
877
 
#else
878
 
        int     rcode;
879
 
 
880
 
        rcode = mkdir(pathname, 0770);
881
 
 
882
 
        if (!(rcode == 0 || (errno == EEXIST && !fail_if_exists))) {
883
 
                /* failure */
884
 
                os_file_handle_error(pathname, "mkdir");
885
 
 
886
 
                return(FALSE);
887
 
        }
888
 
 
889
 
        return (TRUE);
890
 
#endif
891
 
}
892
 
 
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 */
897
 
UNIV_INTERN
898
 
os_file_t
899
 
os_file_create_simple(
900
 
/*==================*/
901
 
        const char*     name,   /*!< in: name of the file or path as a
902
 
                                null-terminated string */
903
 
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file is
904
 
                                opened (if does not exist, error), or
905
 
                                OS_FILE_CREATE if a new file is created
906
 
                                (if exists, error), or
907
 
                                OS_FILE_CREATE_PATH if new file
908
 
                                (if exists, error) and subdirectories along
909
 
                                its path are created (if needed)*/
910
 
        ulint           access_type,/*!< in: OS_FILE_READ_ONLY or
911
 
                                OS_FILE_READ_WRITE */
912
 
        ibool*          success)/*!< out: TRUE if succeed, FALSE if error */
913
 
{
914
 
#ifdef __WIN__
915
 
        os_file_t       file;
916
 
        DWORD           create_flag;
917
 
        DWORD           access;
918
 
        DWORD           attributes      = 0;
919
 
        ibool           retry;
920
 
 
921
 
try_again:
922
 
        ut_a(name);
923
 
 
924
 
        if (create_mode == OS_FILE_OPEN) {
925
 
                create_flag = OPEN_EXISTING;
926
 
        } else if (create_mode == OS_FILE_CREATE) {
927
 
                create_flag = CREATE_NEW;
928
 
        } else if (create_mode == OS_FILE_CREATE_PATH) {
929
 
                /* create subdirs along the path if needed  */
930
 
                *success = os_file_create_subdirs_if_needed(name);
931
 
                if (!*success) {
932
 
                        ut_error;
933
 
                }
934
 
                create_flag = CREATE_NEW;
935
 
                create_mode = OS_FILE_CREATE;
936
 
        } else {
937
 
                create_flag = 0;
938
 
                ut_error;
939
 
        }
940
 
 
941
 
        if (access_type == OS_FILE_READ_ONLY) {
942
 
                access = GENERIC_READ;
943
 
        } else if (access_type == OS_FILE_READ_WRITE) {
944
 
                access = GENERIC_READ | GENERIC_WRITE;
945
 
        } else {
946
 
                access = 0;
947
 
                ut_error;
948
 
        }
949
 
 
950
 
        file = CreateFile((LPCTSTR) name,
951
 
                          access,
952
 
                          FILE_SHARE_READ | FILE_SHARE_WRITE,
953
 
                          /* file can be read and written also
954
 
                          by other processes */
955
 
                          NULL, /* default security attributes */
956
 
                          create_flag,
957
 
                          attributes,
958
 
                          NULL);        /*!< no template file */
959
 
 
960
 
        if (file == INVALID_HANDLE_VALUE) {
961
 
                *success = FALSE;
962
 
 
963
 
                retry = os_file_handle_error(name,
964
 
                                             create_mode == OS_FILE_OPEN ?
965
 
                                             "open" : "create");
966
 
                if (retry) {
967
 
                        goto try_again;
968
 
                }
969
 
        } else {
970
 
                *success = TRUE;
971
 
        }
972
 
 
973
 
        return(file);
974
 
#else /* __WIN__ */
975
 
        os_file_t       file;
976
 
        int             create_flag;
977
 
        ibool           retry;
978
 
 
979
 
try_again:
980
 
        ut_a(name);
981
 
 
982
 
        if (create_mode == OS_FILE_OPEN) {
983
 
                if (access_type == OS_FILE_READ_ONLY) {
984
 
                        create_flag = O_RDONLY;
985
 
                } else {
986
 
                        create_flag = O_RDWR;
987
 
                }
988
 
        } else if (create_mode == OS_FILE_CREATE) {
989
 
                create_flag = O_RDWR | O_CREAT | O_EXCL;
990
 
        } else if (create_mode == OS_FILE_CREATE_PATH) {
991
 
                /* create subdirs along the path if needed  */
992
 
                *success = os_file_create_subdirs_if_needed(name);
993
 
                if (!*success) {
994
 
                        return (-1);
995
 
                }
996
 
                create_flag = O_RDWR | O_CREAT | O_EXCL;
997
 
                create_mode = OS_FILE_CREATE;
998
 
        } else {
999
 
                create_flag = 0;
1000
 
                ut_error;
1001
 
        }
1002
 
 
1003
 
        if (create_mode == OS_FILE_CREATE) {
1004
 
                file = open(name, create_flag, S_IRUSR | S_IWUSR
1005
 
                            | S_IRGRP | S_IWGRP);
1006
 
        } else {
1007
 
                file = open(name, create_flag);
1008
 
        }
1009
 
 
1010
 
        if (file == -1) {
1011
 
                *success = FALSE;
1012
 
 
1013
 
                retry = os_file_handle_error(name,
1014
 
                                             create_mode == OS_FILE_OPEN ?
1015
 
                                             "open" : "create");
1016
 
                if (retry) {
1017
 
                        goto try_again;
1018
 
                }
1019
 
#ifdef USE_FILE_LOCK
1020
 
        } else if (access_type == OS_FILE_READ_WRITE
1021
 
                   && os_file_lock(file, name)) {
1022
 
                *success = FALSE;
1023
 
                close(file);
1024
 
                file = -1;
1025
 
#endif
1026
 
        } else {
1027
 
                *success = TRUE;
1028
 
        }
1029
 
 
1030
 
        return(file);
1031
 
#endif /* __WIN__ */
1032
 
}
1033
 
 
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 */
1038
 
UNIV_INTERN
1039
 
os_file_t
1040
 
os_file_create_simple_no_error_handling(
1041
 
/*====================================*/
1042
 
        const char*     name,   /*!< in: name of the file or path as a
1043
 
                                null-terminated string */
1044
 
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
1045
 
                                is opened (if does not exist, error), or
1046
 
                                OS_FILE_CREATE if a new file is created
1047
 
                                (if exists, error) */
1048
 
        ulint           access_type,/*!< in: OS_FILE_READ_ONLY,
1049
 
                                OS_FILE_READ_WRITE, or
1050
 
                                OS_FILE_READ_ALLOW_DELETE; the last option is
1051
 
                                used by a backup program reading the file */
1052
 
        ibool*          success)/*!< out: TRUE if succeed, FALSE if error */
1053
 
{
1054
 
#ifdef __WIN__
1055
 
        os_file_t       file;
1056
 
        DWORD           create_flag;
1057
 
        DWORD           access;
1058
 
        DWORD           attributes      = 0;
1059
 
        DWORD           share_mode      = FILE_SHARE_READ | FILE_SHARE_WRITE;
1060
 
 
1061
 
        ut_a(name);
1062
 
 
1063
 
        if (create_mode == OS_FILE_OPEN) {
1064
 
                create_flag = OPEN_EXISTING;
1065
 
        } else if (create_mode == OS_FILE_CREATE) {
1066
 
                create_flag = CREATE_NEW;
1067
 
        } else {
1068
 
                create_flag = 0;
1069
 
                ut_error;
1070
 
        }
1071
 
 
1072
 
        if (access_type == OS_FILE_READ_ONLY) {
1073
 
                access = GENERIC_READ;
1074
 
        } else if (access_type == OS_FILE_READ_WRITE) {
1075
 
                access = GENERIC_READ | GENERIC_WRITE;
1076
 
        } else if (access_type == OS_FILE_READ_ALLOW_DELETE) {
1077
 
                access = GENERIC_READ;
1078
 
                share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ
1079
 
                        | FILE_SHARE_WRITE;     /*!< A backup program has to give
1080
 
                                                mysqld the maximum freedom to
1081
 
                                                do what it likes with the
1082
 
                                                file */
1083
 
        } else {
1084
 
                access = 0;
1085
 
                ut_error;
1086
 
        }
1087
 
 
1088
 
        file = CreateFile((LPCTSTR) name,
1089
 
                          access,
1090
 
                          share_mode,
1091
 
                          NULL, /* default security attributes */
1092
 
                          create_flag,
1093
 
                          attributes,
1094
 
                          NULL);        /*!< no template file */
1095
 
 
1096
 
        if (file == INVALID_HANDLE_VALUE) {
1097
 
                *success = FALSE;
1098
 
        } else {
1099
 
                *success = TRUE;
1100
 
        }
1101
 
 
1102
 
        return(file);
1103
 
#else /* __WIN__ */
1104
 
        os_file_t       file;
1105
 
        int             create_flag;
1106
 
 
1107
 
        ut_a(name);
1108
 
 
1109
 
        if (create_mode == OS_FILE_OPEN) {
1110
 
                if (access_type == OS_FILE_READ_ONLY) {
1111
 
                        create_flag = O_RDONLY;
1112
 
                } else {
1113
 
                        create_flag = O_RDWR;
1114
 
                }
1115
 
        } else if (create_mode == OS_FILE_CREATE) {
1116
 
                create_flag = O_RDWR | O_CREAT | O_EXCL;
1117
 
        } else {
1118
 
                create_flag = 0;
1119
 
                ut_error;
1120
 
        }
1121
 
 
1122
 
        if (create_mode == OS_FILE_CREATE) {
1123
 
                file = open(name, create_flag, S_IRUSR | S_IWUSR
1124
 
                            | S_IRGRP | S_IWGRP);
1125
 
        } else {
1126
 
                file = open(name, create_flag);
1127
 
        }
1128
 
 
1129
 
        if (file == -1) {
1130
 
                *success = FALSE;
1131
 
#ifdef USE_FILE_LOCK
1132
 
        } else if (access_type == OS_FILE_READ_WRITE
1133
 
                   && os_file_lock(file, name)) {
1134
 
                *success = FALSE;
1135
 
                close(file);
1136
 
                file = -1;
1137
 
#endif
1138
 
        } else {
1139
 
                *success = TRUE;
1140
 
        }
1141
 
 
1142
 
        return(file);
1143
 
#endif /* __WIN__ */
1144
 
}
1145
 
 
1146
 
/****************************************************************//**
1147
 
Tries to disable OS caching on an opened file descriptor. */
1148
 
UNIV_INTERN
1149
 
void
1150
 
os_file_set_nocache(
1151
 
/*================*/
1152
 
        int             fd,             /*!< in: file descriptor to alter */
1153
 
        const char*     file_name,      /*!< in: file name, used in the
1154
 
                                        diagnostic message */
1155
 
        const char*     operation_name) /*!< in: "open" or "create"; used in the
1156
 
                                        diagnostic message */
1157
 
{
1158
 
        /* some versions of Solaris may not have DIRECTIO_ON */
1159
 
#if defined(UNIV_SOLARIS) && defined(DIRECTIO_ON)
1160
 
        if (directio(fd, DIRECTIO_ON) == -1) {
1161
 
                int     errno_save;
1162
 
                errno_save = (int)errno;
1163
 
                ut_print_timestamp(stderr);
1164
 
                fprintf(stderr,
1165
 
                        "  InnoDB: Failed to set DIRECTIO_ON "
1166
 
                        "on file %s: %s: %s, continuing anyway\n",
1167
 
                        file_name, operation_name, strerror(errno_save));
1168
 
        }
1169
 
#elif defined(O_DIRECT)
1170
 
        if (fcntl(fd, F_SETFL, O_DIRECT) == -1) {
1171
 
                int     errno_save;
1172
 
                errno_save = (int)errno;
1173
 
                ut_print_timestamp(stderr);
1174
 
                fprintf(stderr,
1175
 
                        "  InnoDB: Failed to set O_DIRECT "
1176
 
                        "on file %s: %s: %s, continuing anyway\n",
1177
 
                        file_name, operation_name, strerror(errno_save));
1178
 
                if (errno_save == EINVAL) {
1179
 
                        ut_print_timestamp(stderr);
1180
 
                        fprintf(stderr,
1181
 
                                "  InnoDB: O_DIRECT is known to result in "
1182
 
                                "'Invalid argument' on Linux on tmpfs, "
1183
 
                                "see MySQL Bug#26662\n");
1184
 
                }
1185
 
        }
1186
 
#else /* Required for OSX */
1187
 
        (void)fd;
1188
 
        (void)file_name;
1189
 
        (void)operation_name;
1190
 
#endif
1191
 
}
1192
 
 
1193
 
/****************************************************************//**
1194
 
Opens an existing file or creates a new.
1195
 
@return own: handle to the file, not defined if error, error number
1196
 
can be retrieved with os_file_get_last_error */
1197
 
UNIV_INTERN
1198
 
os_file_t
1199
 
os_file_create(
1200
 
/*===========*/
1201
 
        const char*     name,   /*!< in: name of the file or path as a
1202
 
                                null-terminated string */
1203
 
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
1204
 
                                is opened (if does not exist, error), or
1205
 
                                OS_FILE_CREATE if a new file is created
1206
 
                                (if exists, error),
1207
 
                                OS_FILE_OVERWRITE if a new file is created
1208
 
                                or an old overwritten;
1209
 
                                OS_FILE_OPEN_RAW, if a raw device or disk
1210
 
                                partition should be opened */
1211
 
        ulint           purpose,/*!< in: OS_FILE_AIO, if asynchronous,
1212
 
                                non-buffered i/o is desired,
1213
 
                                OS_FILE_NORMAL, if any normal file;
1214
 
                                NOTE that it also depends on type, os_aio_..
1215
 
                                and srv_.. variables whether we really use
1216
 
                                async i/o or unbuffered i/o: look in the
1217
 
                                function source code for the exact rules */
1218
 
        ulint           type,   /*!< in: OS_DATA_FILE or OS_LOG_FILE */
1219
 
        ibool*          success)/*!< out: TRUE if succeed, FALSE if error */
1220
 
{
1221
 
#ifdef __WIN__
1222
 
        os_file_t       file;
1223
 
        DWORD           share_mode      = FILE_SHARE_READ;
1224
 
        DWORD           create_flag;
1225
 
        DWORD           attributes;
1226
 
        ibool           retry;
1227
 
try_again:
1228
 
        ut_a(name);
1229
 
 
1230
 
        if (create_mode == OS_FILE_OPEN_RAW) {
1231
 
                create_flag = OPEN_EXISTING;
1232
 
                share_mode = FILE_SHARE_WRITE;
1233
 
        } else if (create_mode == OS_FILE_OPEN
1234
 
                   || create_mode == OS_FILE_OPEN_RETRY) {
1235
 
                create_flag = OPEN_EXISTING;
1236
 
        } else if (create_mode == OS_FILE_CREATE) {
1237
 
                create_flag = CREATE_NEW;
1238
 
        } else if (create_mode == OS_FILE_OVERWRITE) {
1239
 
                create_flag = CREATE_ALWAYS;
1240
 
        } else {
1241
 
                create_flag = 0;
1242
 
                ut_error;
1243
 
        }
1244
 
 
1245
 
        if (purpose == OS_FILE_AIO) {
1246
 
                /* If specified, use asynchronous (overlapped) io and no
1247
 
                buffering of writes in the OS */
1248
 
                attributes = 0;
1249
 
#ifdef WIN_ASYNC_IO
1250
 
                if (os_aio_use_native_aio) {
1251
 
                        attributes = attributes | FILE_FLAG_OVERLAPPED;
1252
 
                }
1253
 
#endif
1254
 
#ifdef UNIV_NON_BUFFERED_IO
1255
 
                if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
1256
 
                        /* Do not use unbuffered i/o to log files because
1257
 
                        value 2 denotes that we do not flush the log at every
1258
 
                        commit, but only once per second */
1259
 
                } else if (srv_win_file_flush_method
1260
 
                           == SRV_WIN_IO_UNBUFFERED) {
1261
 
                        attributes = attributes | FILE_FLAG_NO_BUFFERING;
1262
 
                }
1263
 
#endif
1264
 
        } else if (purpose == OS_FILE_NORMAL) {
1265
 
                attributes = 0;
1266
 
#ifdef UNIV_NON_BUFFERED_IO
1267
 
                if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
1268
 
                        /* Do not use unbuffered i/o to log files because
1269
 
                        value 2 denotes that we do not flush the log at every
1270
 
                        commit, but only once per second */
1271
 
                } else if (srv_win_file_flush_method
1272
 
                           == SRV_WIN_IO_UNBUFFERED) {
1273
 
                        attributes = attributes | FILE_FLAG_NO_BUFFERING;
1274
 
                }
1275
 
#endif
1276
 
        } else {
1277
 
                attributes = 0;
1278
 
                ut_error;
1279
 
        }
1280
 
 
1281
 
        file = CreateFile((LPCTSTR) name,
1282
 
                          GENERIC_READ | GENERIC_WRITE, /* read and write
1283
 
                                                        access */
1284
 
                          share_mode,   /* File can be read also by other
1285
 
                                        processes; we must give the read
1286
 
                                        permission because of ibbackup. We do
1287
 
                                        not give the write permission to
1288
 
                                        others because if one would succeed to
1289
 
                                        start 2 instances of mysqld on the
1290
 
                                        SAME files, that could cause severe
1291
 
                                        database corruption! When opening
1292
 
                                        raw disk partitions, Microsoft manuals
1293
 
                                        say that we must give also the write
1294
 
                                        permission. */
1295
 
                          NULL, /* default security attributes */
1296
 
                          create_flag,
1297
 
                          attributes,
1298
 
                          NULL);        /*!< no template file */
1299
 
 
1300
 
        if (file == INVALID_HANDLE_VALUE) {
1301
 
                *success = FALSE;
1302
 
 
1303
 
                /* When srv_file_per_table is on, file creation failure may not
1304
 
                be critical to the whole instance. Do not crash the server in
1305
 
                case of unknown errors. */
1306
 
                if (srv_file_per_table) {
1307
 
                        retry = os_file_handle_error_no_exit(name,
1308
 
                                                create_mode == OS_FILE_CREATE ?
1309
 
                                                "create" : "open");
1310
 
                } else {
1311
 
                        retry = os_file_handle_error(name,
1312
 
                                                create_mode == OS_FILE_CREATE ?
1313
 
                                                "create" : "open");
1314
 
                }
1315
 
 
1316
 
                if (retry) {
1317
 
                        goto try_again;
1318
 
                }
1319
 
        } else {
1320
 
                *success = TRUE;
1321
 
        }
1322
 
 
1323
 
        return(file);
1324
 
#else /* __WIN__ */
1325
 
        os_file_t       file;
1326
 
        int             create_flag;
1327
 
        ibool           retry;
1328
 
        const char*     mode_str        = NULL;
1329
 
        const char*     type_str        = NULL;
1330
 
        const char*     purpose_str     = NULL;
1331
 
 
1332
 
try_again:
1333
 
        ut_a(name);
1334
 
 
1335
 
        if (create_mode == OS_FILE_OPEN || create_mode == OS_FILE_OPEN_RAW
1336
 
            || create_mode == OS_FILE_OPEN_RETRY) {
1337
 
                mode_str = "OPEN";
1338
 
                create_flag = O_RDWR;
1339
 
        } else if (create_mode == OS_FILE_CREATE) {
1340
 
                mode_str = "CREATE";
1341
 
                create_flag = O_RDWR | O_CREAT | O_EXCL;
1342
 
        } else if (create_mode == OS_FILE_OVERWRITE) {
1343
 
                mode_str = "OVERWRITE";
1344
 
                create_flag = O_RDWR | O_CREAT | O_TRUNC;
1345
 
        } else {
1346
 
                create_flag = 0;
1347
 
                ut_error;
1348
 
        }
1349
 
 
1350
 
        if (type == OS_LOG_FILE) {
1351
 
                type_str = "LOG";
1352
 
        } else if (type == OS_DATA_FILE) {
1353
 
                type_str = "DATA";
1354
 
        } else {
1355
 
                ut_error;
1356
 
        }
1357
 
 
1358
 
        if (purpose == OS_FILE_AIO) {
1359
 
                purpose_str = "AIO";
1360
 
        } else if (purpose == OS_FILE_NORMAL) {
1361
 
                purpose_str = "NORMAL";
1362
 
        } else {
1363
 
                ut_error;
1364
 
        }
1365
 
 
1366
 
#if 0
1367
 
        fprintf(stderr, "Opening file %s, mode %s, type %s, purpose %s\n",
1368
 
                name, mode_str, type_str, purpose_str);
1369
 
#endif
1370
 
#ifdef O_SYNC
1371
 
        /* We let O_SYNC only affect log files; note that we map O_DSYNC to
1372
 
        O_SYNC because the datasync options seemed to corrupt files in 2001
1373
 
        in both Linux and Solaris */
1374
 
        if (type == OS_LOG_FILE
1375
 
            && srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) {
1376
 
 
1377
 
# if 0
1378
 
                fprintf(stderr, "Using O_SYNC for file %s\n", name);
1379
 
# endif
1380
 
 
1381
 
                create_flag = create_flag | O_SYNC;
1382
 
        }
1383
 
#endif /* O_SYNC */
1384
 
 
1385
 
        file = open(name, create_flag, os_innodb_umask);
1386
 
 
1387
 
        if (file == -1) {
1388
 
                *success = FALSE;
1389
 
 
1390
 
                /* When srv_file_per_table is on, file creation failure may not
1391
 
                be critical to the whole instance. Do not crash the server in
1392
 
                case of unknown errors. */
1393
 
                if (srv_file_per_table) {
1394
 
                        retry = os_file_handle_error_no_exit(name,
1395
 
                                                create_mode == OS_FILE_CREATE ?
1396
 
                                                "create" : "open");
1397
 
                } else {
1398
 
                        retry = os_file_handle_error(name,
1399
 
                                                create_mode == OS_FILE_CREATE ?
1400
 
                                                "create" : "open");
1401
 
                }
1402
 
 
1403
 
                if (retry) {
1404
 
                        goto try_again;
1405
 
                } else {
1406
 
                        return(file /* -1 */);
1407
 
                }
1408
 
        }
1409
 
        /* else */
1410
 
 
1411
 
        *success = TRUE;
1412
 
 
1413
 
        /* We disable OS caching (O_DIRECT) only on data files */
1414
 
        if (type != OS_LOG_FILE
1415
 
            && srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
1416
 
                
1417
 
                os_file_set_nocache(file, name, mode_str);
1418
 
        }
1419
 
 
1420
 
#ifdef USE_FILE_LOCK
1421
 
        if (create_mode != OS_FILE_OPEN_RAW && os_file_lock(file, name)) {
1422
 
 
1423
 
                if (create_mode == OS_FILE_OPEN_RETRY) {
1424
 
                        int i;
1425
 
                        ut_print_timestamp(stderr);
1426
 
                        fputs("  InnoDB: Retrying to lock"
1427
 
                              " the first data file\n",
1428
 
                              stderr);
1429
 
                        for (i = 0; i < 100; i++) {
1430
 
                                os_thread_sleep(1000000);
1431
 
                                if (!os_file_lock(file, name)) {
1432
 
                                        *success = TRUE;
1433
 
                                        return(file);
1434
 
                                }
1435
 
                        }
1436
 
                        ut_print_timestamp(stderr);
1437
 
                        fputs("  InnoDB: Unable to open the first data file\n",
1438
 
                              stderr);
1439
 
                }
1440
 
 
1441
 
                *success = FALSE;
1442
 
                close(file);
1443
 
                file = -1;
1444
 
        }
1445
 
#endif /* USE_FILE_LOCK */
1446
 
 
1447
 
        return(file);
1448
 
#endif /* __WIN__ */
1449
 
}
1450
 
 
1451
 
/***********************************************************************//**
1452
 
Deletes a file if it exists. The file has to be closed before calling this.
1453
 
@return TRUE if success */
1454
 
UNIV_INTERN
1455
 
ibool
1456
 
os_file_delete_if_exists(
1457
 
/*=====================*/
1458
 
        const char*     name)   /*!< in: file path as a null-terminated string */
1459
 
{
1460
 
#ifdef __WIN__
1461
 
        BOOL    ret;
1462
 
        ulint   count   = 0;
1463
 
loop:
1464
 
        /* In Windows, deleting an .ibd file may fail if ibbackup is copying
1465
 
        it */
1466
 
 
1467
 
        ret = DeleteFile((LPCTSTR)name);
1468
 
 
1469
 
        if (ret) {
1470
 
                return(TRUE);
1471
 
        }
1472
 
 
1473
 
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
1474
 
                /* the file does not exist, this not an error */
1475
 
 
1476
 
                return(TRUE);
1477
 
        }
1478
 
 
1479
 
        count++;
1480
 
 
1481
 
        if (count > 100 && 0 == (count % 10)) {
1482
 
                fprintf(stderr,
1483
 
                        "InnoDB: Warning: cannot delete file %s\n"
1484
 
                        "InnoDB: Are you running ibbackup"
1485
 
                        " to back up the file?\n", name);
1486
 
 
1487
 
                os_file_get_last_error(TRUE); /* print error information */
1488
 
        }
1489
 
 
1490
 
        os_thread_sleep(1000000);       /* sleep for a second */
1491
 
 
1492
 
        if (count > 2000) {
1493
 
 
1494
 
                return(FALSE);
1495
 
        }
1496
 
 
1497
 
        goto loop;
1498
 
#else
1499
 
        int     ret;
1500
 
 
1501
 
        ret = unlink(name);
1502
 
 
1503
 
        if (ret != 0 && errno != ENOENT) {
1504
 
                os_file_handle_error_no_exit(name, "delete");
1505
 
 
1506
 
                return(FALSE);
1507
 
        }
1508
 
 
1509
 
        return(TRUE);
1510
 
#endif
1511
 
}
1512
 
 
1513
 
/***********************************************************************//**
1514
 
Deletes a file. The file has to be closed before calling this.
1515
 
@return TRUE if success */
1516
 
UNIV_INTERN
1517
 
ibool
1518
 
os_file_delete(
1519
 
/*===========*/
1520
 
        const char*     name)   /*!< in: file path as a null-terminated string */
1521
 
{
1522
 
#ifdef __WIN__
1523
 
        BOOL    ret;
1524
 
        ulint   count   = 0;
1525
 
loop:
1526
 
        /* In Windows, deleting an .ibd file may fail if ibbackup is copying
1527
 
        it */
1528
 
 
1529
 
        ret = DeleteFile((LPCTSTR)name);
1530
 
 
1531
 
        if (ret) {
1532
 
                return(TRUE);
1533
 
        }
1534
 
 
1535
 
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
1536
 
                /* If the file does not exist, we classify this as a 'mild'
1537
 
                error and return */
1538
 
 
1539
 
                return(FALSE);
1540
 
        }
1541
 
 
1542
 
        count++;
1543
 
 
1544
 
        if (count > 100 && 0 == (count % 10)) {
1545
 
                fprintf(stderr,
1546
 
                        "InnoDB: Warning: cannot delete file %s\n"
1547
 
                        "InnoDB: Are you running ibbackup"
1548
 
                        " to back up the file?\n", name);
1549
 
 
1550
 
                os_file_get_last_error(TRUE); /* print error information */
1551
 
        }
1552
 
 
1553
 
        os_thread_sleep(1000000);       /* sleep for a second */
1554
 
 
1555
 
        if (count > 2000) {
1556
 
 
1557
 
                return(FALSE);
1558
 
        }
1559
 
 
1560
 
        goto loop;
1561
 
#else
1562
 
        int     ret;
1563
 
 
1564
 
        ret = unlink(name);
1565
 
 
1566
 
        if (ret != 0) {
1567
 
                os_file_handle_error_no_exit(name, "delete");
1568
 
 
1569
 
                return(FALSE);
1570
 
        }
1571
 
 
1572
 
        return(TRUE);
1573
 
#endif
1574
 
}
1575
 
 
1576
 
/***********************************************************************//**
1577
 
Renames a file (can also move it to another directory). It is safest that the
1578
 
file is closed before calling this function.
1579
 
@return TRUE if success */
1580
 
UNIV_INTERN
1581
 
ibool
1582
 
os_file_rename(
1583
 
/*===========*/
1584
 
        const char*     oldpath,/*!< in: old file path as a null-terminated
1585
 
                                string */
1586
 
        const char*     newpath)/*!< in: new file path */
1587
 
{
1588
 
#ifdef __WIN__
1589
 
        BOOL    ret;
1590
 
 
1591
 
        ret = MoveFile((LPCTSTR)oldpath, (LPCTSTR)newpath);
1592
 
 
1593
 
        if (ret) {
1594
 
                return(TRUE);
1595
 
        }
1596
 
 
1597
 
        os_file_handle_error_no_exit(oldpath, "rename");
1598
 
 
1599
 
        return(FALSE);
1600
 
#else
1601
 
        int     ret;
1602
 
 
1603
 
        ret = rename(oldpath, newpath);
1604
 
 
1605
 
        if (ret != 0) {
1606
 
                os_file_handle_error_no_exit(oldpath, "rename");
1607
 
 
1608
 
                return(FALSE);
1609
 
        }
1610
 
 
1611
 
        return(TRUE);
1612
 
#endif
1613
 
}
1614
 
 
1615
 
/***********************************************************************//**
1616
 
Closes a file handle. In case of error, error number can be retrieved with
1617
 
os_file_get_last_error.
1618
 
@return TRUE if success */
1619
 
UNIV_INTERN
1620
 
ibool
1621
 
os_file_close(
1622
 
/*==========*/
1623
 
        os_file_t       file)   /*!< in, own: handle to a file */
1624
 
{
1625
 
#ifdef __WIN__
1626
 
        BOOL    ret;
1627
 
 
1628
 
        ut_a(file);
1629
 
 
1630
 
        ret = CloseHandle(file);
1631
 
 
1632
 
        if (ret) {
1633
 
                return(TRUE);
1634
 
        }
1635
 
 
1636
 
        os_file_handle_error(NULL, "close");
1637
 
 
1638
 
        return(FALSE);
1639
 
#else
1640
 
        int     ret;
1641
 
 
1642
 
        ret = close(file);
1643
 
 
1644
 
        if (ret == -1) {
1645
 
                os_file_handle_error(NULL, "close");
1646
 
 
1647
 
                return(FALSE);
1648
 
        }
1649
 
 
1650
 
        return(TRUE);
1651
 
#endif
1652
 
}
1653
 
 
1654
 
#ifdef UNIV_HOTBACKUP
1655
 
/***********************************************************************//**
1656
 
Closes a file handle.
1657
 
@return TRUE if success */
1658
 
UNIV_INTERN
1659
 
ibool
1660
 
os_file_close_no_error_handling(
1661
 
/*============================*/
1662
 
        os_file_t       file)   /*!< in, own: handle to a file */
1663
 
{
1664
 
#ifdef __WIN__
1665
 
        BOOL    ret;
1666
 
 
1667
 
        ut_a(file);
1668
 
 
1669
 
        ret = CloseHandle(file);
1670
 
 
1671
 
        if (ret) {
1672
 
                return(TRUE);
1673
 
        }
1674
 
 
1675
 
        return(FALSE);
1676
 
#else
1677
 
        int     ret;
1678
 
 
1679
 
        ret = close(file);
1680
 
 
1681
 
        if (ret == -1) {
1682
 
 
1683
 
                return(FALSE);
1684
 
        }
1685
 
 
1686
 
        return(TRUE);
1687
 
#endif
1688
 
}
1689
 
#endif /* UNIV_HOTBACKUP */
1690
 
 
1691
 
/***********************************************************************//**
1692
 
Gets a file size.
1693
 
@return TRUE if success */
1694
 
UNIV_INTERN
1695
 
ibool
1696
 
os_file_get_size(
1697
 
/*=============*/
1698
 
        os_file_t       file,   /*!< in: handle to a file */
1699
 
        ulint*          size,   /*!< out: least significant 32 bits of file
1700
 
                                size */
1701
 
        ulint*          size_high)/*!< out: most significant 32 bits of size */
1702
 
{
1703
 
#ifdef __WIN__
1704
 
        DWORD   high;
1705
 
        DWORD   low;
1706
 
 
1707
 
        low = GetFileSize(file, &high);
1708
 
 
1709
 
        if ((low == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) {
1710
 
                return(FALSE);
1711
 
        }
1712
 
 
1713
 
        *size = low;
1714
 
        *size_high = high;
1715
 
 
1716
 
        return(TRUE);
1717
 
#else
1718
 
        off_t   offs;
1719
 
 
1720
 
        offs = lseek(file, 0, SEEK_END);
1721
 
 
1722
 
        if (offs == ((off_t)-1)) {
1723
 
 
1724
 
                return(FALSE);
1725
 
        }
1726
 
 
1727
 
        if (sizeof(off_t) > 4) {
1728
 
                *size = (ulint)(offs & 0xFFFFFFFFUL);
1729
 
                *size_high = (ulint)(offs >> 32);
1730
 
        } else {
1731
 
                *size = (ulint) offs;
1732
 
                *size_high = 0;
1733
 
        }
1734
 
 
1735
 
        return(TRUE);
1736
 
#endif
1737
 
}
1738
 
 
1739
 
/***********************************************************************//**
1740
 
Gets file size as a 64-bit integer ib_int64_t.
1741
 
@return size in bytes, -1 if error */
1742
 
UNIV_INTERN
1743
 
ib_int64_t
1744
 
os_file_get_size_as_iblonglong(
1745
 
/*===========================*/
1746
 
        os_file_t       file)   /*!< in: handle to a file */
1747
 
{
1748
 
        ulint   size;
1749
 
        ulint   size_high;
1750
 
        ibool   success;
1751
 
 
1752
 
        success = os_file_get_size(file, &size, &size_high);
1753
 
 
1754
 
        if (!success) {
1755
 
 
1756
 
                return(-1);
1757
 
        }
1758
 
 
1759
 
        return((((ib_int64_t)size_high) << 32) + (ib_int64_t)size);
1760
 
}
1761
 
 
1762
 
/***********************************************************************//**
1763
 
Write the specified number of zeros to a newly created file.
1764
 
@return TRUE if success */
1765
 
UNIV_INTERN
1766
 
ibool
1767
 
os_file_set_size(
1768
 
/*=============*/
1769
 
        const char*     name,   /*!< in: name of the file or path as a
1770
 
                                null-terminated string */
1771
 
        os_file_t       file,   /*!< in: handle to a file */
1772
 
        ulint           size,   /*!< in: least significant 32 bits of file
1773
 
                                size */
1774
 
        ulint           size_high)/*!< in: most significant 32 bits of size */
1775
 
{
1776
 
        ib_int64_t      current_size;
1777
 
        ib_int64_t      desired_size;
1778
 
        ibool           ret;
1779
 
        byte*           buf;
1780
 
        byte*           buf2;
1781
 
        ulint           buf_size;
1782
 
 
1783
 
        ut_a(size == (size & 0xFFFFFFFF));
1784
 
 
1785
 
        current_size = 0;
1786
 
        desired_size = (ib_int64_t)size + (((ib_int64_t)size_high) << 32);
1787
 
 
1788
 
        /* Write up to 1 megabyte at a time. */
1789
 
        buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE))
1790
 
                * UNIV_PAGE_SIZE;
1791
 
        buf2 = ut_malloc(buf_size + UNIV_PAGE_SIZE);
1792
 
 
1793
 
        /* Align the buffer for possible raw i/o */
1794
 
        buf = ut_align(buf2, UNIV_PAGE_SIZE);
1795
 
 
1796
 
        /* Write buffer full of zeros */
1797
 
        memset(buf, 0, buf_size);
1798
 
 
1799
 
        if (desired_size >= (ib_int64_t)(100 * 1024 * 1024)) {
1800
 
 
1801
 
                fprintf(stderr, "InnoDB: Progress in MB:");
1802
 
        }
1803
 
 
1804
 
        while (current_size < desired_size) {
1805
 
                ulint   n_bytes;
1806
 
 
1807
 
                if (desired_size - current_size < (ib_int64_t) buf_size) {
1808
 
                        n_bytes = (ulint) (desired_size - current_size);
1809
 
                } else {
1810
 
                        n_bytes = buf_size;
1811
 
                }
1812
 
 
1813
 
                ret = os_file_write(name, file, buf,
1814
 
                                    (ulint)(current_size & 0xFFFFFFFF),
1815
 
                                    (ulint)(current_size >> 32),
1816
 
                                    n_bytes);
1817
 
                if (!ret) {
1818
 
                        ut_free(buf2);
1819
 
                        goto error_handling;
1820
 
                }
1821
 
 
1822
 
                /* Print about progress for each 100 MB written */
1823
 
                if ((ib_int64_t) (current_size + n_bytes) / (ib_int64_t)(100 * 1024 * 1024)
1824
 
                    != current_size / (ib_int64_t)(100 * 1024 * 1024)) {
1825
 
 
1826
 
                        fprintf(stderr, " %lu00",
1827
 
                                (ulong) ((current_size + n_bytes)
1828
 
                                         / (ib_int64_t)(100 * 1024 * 1024)));
1829
 
                }
1830
 
 
1831
 
                current_size += n_bytes;
1832
 
        }
1833
 
 
1834
 
        if (desired_size >= (ib_int64_t)(100 * 1024 * 1024)) {
1835
 
 
1836
 
                fprintf(stderr, "\n");
1837
 
        }
1838
 
 
1839
 
        ut_free(buf2);
1840
 
 
1841
 
        ret = os_file_flush(file);
1842
 
 
1843
 
        if (ret) {
1844
 
                return(TRUE);
1845
 
        }
1846
 
 
1847
 
error_handling:
1848
 
        return(FALSE);
1849
 
}
1850
 
 
1851
 
/***********************************************************************//**
1852
 
Truncates a file at its current position.
1853
 
@return TRUE if success */
1854
 
UNIV_INTERN
1855
 
ibool
1856
 
os_file_set_eof(
1857
 
/*============*/
1858
 
        FILE*           file)   /*!< in: file to be truncated */
1859
 
{
1860
 
#ifdef __WIN__
1861
 
        HANDLE h = (HANDLE) _get_osfhandle(fileno(file));
1862
 
        return(SetEndOfFile(h));
1863
 
#else /* __WIN__ */
1864
 
        return(!ftruncate(fileno(file), ftell(file)));
1865
 
#endif /* __WIN__ */
1866
 
}
1867
 
 
1868
 
#ifndef __WIN__
1869
 
/***********************************************************************//**
1870
 
Wrapper to fsync(2) that retries the call on some errors.
1871
 
Returns the value 0 if successful; otherwise the value -1 is returned and
1872
 
the global variable errno is set to indicate the error.
1873
 
@return 0 if success, -1 otherwise */
1874
 
 
1875
 
static
1876
 
int
1877
 
os_file_fsync(
1878
 
/*==========*/
1879
 
        os_file_t       file)   /*!< in: handle to a file */
1880
 
{
1881
 
        int     ret;
1882
 
        int     failures;
1883
 
        ibool   retry;
1884
 
 
1885
 
        failures = 0;
1886
 
 
1887
 
        do {
1888
 
                ret = fsync(file);
1889
 
 
1890
 
                os_n_fsyncs++;
1891
 
 
1892
 
                if (ret == -1 && errno == ENOLCK) {
1893
 
 
1894
 
                        if (failures % 100 == 0) {
1895
 
 
1896
 
                                ut_print_timestamp(stderr);
1897
 
                                fprintf(stderr,
1898
 
                                        "  InnoDB: fsync(): "
1899
 
                                        "No locks available; retrying\n");
1900
 
                        }
1901
 
 
1902
 
                        os_thread_sleep(200000 /* 0.2 sec */);
1903
 
 
1904
 
                        failures++;
1905
 
 
1906
 
                        retry = TRUE;
1907
 
                } else {
1908
 
 
1909
 
                        retry = FALSE;
1910
 
                }
1911
 
        } while (retry);
1912
 
 
1913
 
        return(ret);
1914
 
}
1915
 
#endif /* !__WIN__ */
1916
 
 
1917
 
/***********************************************************************//**
1918
 
Flushes the write buffers of a given file to the disk.
1919
 
@return TRUE if success */
1920
 
UNIV_INTERN
1921
 
ibool
1922
 
os_file_flush(
1923
 
/*==========*/
1924
 
        os_file_t       file)   /*!< in, own: handle to a file */
1925
 
{
1926
 
#ifdef __WIN__
1927
 
        BOOL    ret;
1928
 
 
1929
 
        ut_a(file);
1930
 
 
1931
 
        os_n_fsyncs++;
1932
 
 
1933
 
        ret = FlushFileBuffers(file);
1934
 
 
1935
 
        if (ret) {
1936
 
                return(TRUE);
1937
 
        }
1938
 
 
1939
 
        /* Since Windows returns ERROR_INVALID_FUNCTION if the 'file' is
1940
 
        actually a raw device, we choose to ignore that error if we are using
1941
 
        raw disks */
1942
 
 
1943
 
        if (srv_start_raw_disk_in_use && GetLastError()
1944
 
            == ERROR_INVALID_FUNCTION) {
1945
 
                return(TRUE);
1946
 
        }
1947
 
 
1948
 
        os_file_handle_error(NULL, "flush");
1949
 
 
1950
 
        /* It is a fatal error if a file flush does not succeed, because then
1951
 
        the database can get corrupt on disk */
1952
 
        ut_error;
1953
 
 
1954
 
        return(FALSE);
1955
 
#else
1956
 
        int     ret;
1957
 
 
1958
 
#if defined(HAVE_DARWIN_THREADS)
1959
 
# ifndef F_FULLFSYNC
1960
 
        /* The following definition is from the Mac OS X 10.3 <sys/fcntl.h> */
1961
 
#  define F_FULLFSYNC 51 /* fsync + ask the drive to flush to the media */
1962
 
# elif F_FULLFSYNC != 51
1963
 
#  error "F_FULLFSYNC != 51: ABI incompatibility with Mac OS X 10.3"
1964
 
# endif
1965
 
        /* Apple has disabled fsync() for internal disk drives in OS X. That
1966
 
        caused corruption for a user when he tested a power outage. Let us in
1967
 
        OS X use a nonstandard flush method recommended by an Apple
1968
 
        engineer. */
1969
 
 
1970
 
        if (!srv_have_fullfsync) {
1971
 
                /* If we are not on an operating system that supports this,
1972
 
                then fall back to a plain fsync. */
1973
 
 
1974
 
                ret = os_file_fsync(file);
1975
 
        } else {
1976
 
                ret = fcntl(file, F_FULLFSYNC, NULL);
1977
 
 
1978
 
                if (ret) {
1979
 
                        /* If we are not on a file system that supports this,
1980
 
                        then fall back to a plain fsync. */
1981
 
                        ret = os_file_fsync(file);
1982
 
                }
1983
 
        }
1984
 
#else
1985
 
        ret = os_file_fsync(file);
1986
 
#endif
1987
 
 
1988
 
        if (ret == 0) {
1989
 
                return(TRUE);
1990
 
        }
1991
 
 
1992
 
        /* Since Linux returns EINVAL if the 'file' is actually a raw device,
1993
 
        we choose to ignore that error if we are using raw disks */
1994
 
 
1995
 
        if (srv_start_raw_disk_in_use && errno == EINVAL) {
1996
 
 
1997
 
                return(TRUE);
1998
 
        }
1999
 
 
2000
 
        ut_print_timestamp(stderr);
2001
 
 
2002
 
        fprintf(stderr,
2003
 
                "  InnoDB: Error: the OS said file flush did not succeed\n");
2004
 
 
2005
 
        os_file_handle_error(NULL, "flush");
2006
 
 
2007
 
        /* It is a fatal error if a file flush does not succeed, because then
2008
 
        the database can get corrupt on disk */
2009
 
        ut_error;
2010
 
 
2011
 
        return(FALSE);
2012
 
#endif
2013
 
}
2014
 
 
2015
 
#ifndef __WIN__
2016
 
/*******************************************************************//**
2017
 
Does a synchronous read operation in Posix.
2018
 
@return number of bytes read, -1 if error */
2019
 
static
2020
 
ssize_t
2021
 
os_file_pread(
2022
 
/*==========*/
2023
 
        os_file_t       file,   /*!< in: handle to a file */
2024
 
        void*           buf,    /*!< in: buffer where to read */
2025
 
        ulint           n,      /*!< in: number of bytes to read */
2026
 
        ulint           offset, /*!< in: least significant 32 bits of file
2027
 
                                offset from where to read */
2028
 
        ulint           offset_high) /*!< in: most significant 32 bits of
2029
 
                                offset */
2030
 
{
2031
 
        off_t   offs;
2032
 
        ssize_t n_bytes;
2033
 
 
2034
 
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2035
 
 
2036
 
        /* If off_t is > 4 bytes in size, then we assume we can pass a
2037
 
        64-bit address */
2038
 
 
2039
 
        if (sizeof(off_t) > 4) {
2040
 
                offs = (off_t)offset + (((off_t)offset_high) << 32);
2041
 
 
2042
 
        } else {
2043
 
                offs = (off_t)offset;
2044
 
 
2045
 
                if (offset_high > 0) {
2046
 
                        fprintf(stderr,
2047
 
                                "InnoDB: Error: file read at offset > 4 GB\n");
2048
 
                }
2049
 
        }
2050
 
 
2051
 
        os_n_file_reads++;
2052
 
 
2053
 
#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
2054
 
        os_mutex_enter(os_file_count_mutex);
2055
 
        os_file_n_pending_preads++;
2056
 
        os_n_pending_reads++;
2057
 
        os_mutex_exit(os_file_count_mutex);
2058
 
 
2059
 
        n_bytes = pread(file, buf, (ssize_t)n, offs);
2060
 
 
2061
 
        os_mutex_enter(os_file_count_mutex);
2062
 
        os_file_n_pending_preads--;
2063
 
        os_n_pending_reads--;
2064
 
        os_mutex_exit(os_file_count_mutex);
2065
 
 
2066
 
        return(n_bytes);
2067
 
#else
2068
 
        {
2069
 
                off_t   ret_offset;
2070
 
                ssize_t ret;
2071
 
                ulint   i;
2072
 
 
2073
 
                os_mutex_enter(os_file_count_mutex);
2074
 
                os_n_pending_reads++;
2075
 
                os_mutex_exit(os_file_count_mutex);
2076
 
 
2077
 
                /* Protect the seek / read operation with a mutex */
2078
 
                i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2079
 
 
2080
 
                os_mutex_enter(os_file_seek_mutexes[i]);
2081
 
 
2082
 
                ret_offset = lseek(file, offs, SEEK_SET);
2083
 
 
2084
 
                if (ret_offset < 0) {
2085
 
                        ret = -1;
2086
 
                } else {
2087
 
                        ret = read(file, buf, (ssize_t)n);
2088
 
                }
2089
 
 
2090
 
                os_mutex_exit(os_file_seek_mutexes[i]);
2091
 
 
2092
 
                os_mutex_enter(os_file_count_mutex);
2093
 
                os_n_pending_reads--;
2094
 
                os_mutex_exit(os_file_count_mutex);
2095
 
 
2096
 
                return(ret);
2097
 
        }
2098
 
#endif
2099
 
}
2100
 
 
2101
 
/*******************************************************************//**
2102
 
Does a synchronous write operation in Posix.
2103
 
@return number of bytes written, -1 if error */
2104
 
static
2105
 
ssize_t
2106
 
os_file_pwrite(
2107
 
/*===========*/
2108
 
        os_file_t       file,   /*!< in: handle to a file */
2109
 
        const void*     buf,    /*!< in: buffer from where to write */
2110
 
        ulint           n,      /*!< in: number of bytes to write */
2111
 
        ulint           offset, /*!< in: least significant 32 bits of file
2112
 
                                offset where to write */
2113
 
        ulint           offset_high) /*!< in: most significant 32 bits of
2114
 
                                offset */
2115
 
{
2116
 
        ssize_t ret;
2117
 
        off_t   offs;
2118
 
 
2119
 
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2120
 
 
2121
 
        /* If off_t is > 4 bytes in size, then we assume we can pass a
2122
 
        64-bit address */
2123
 
 
2124
 
        if (sizeof(off_t) > 4) {
2125
 
                offs = (off_t)offset + (((off_t)offset_high) << 32);
2126
 
        } else {
2127
 
                offs = (off_t)offset;
2128
 
 
2129
 
                if (offset_high > 0) {
2130
 
                        fprintf(stderr,
2131
 
                                "InnoDB: Error: file write"
2132
 
                                " at offset > 4 GB\n");
2133
 
                }
2134
 
        }
2135
 
 
2136
 
        os_n_file_writes++;
2137
 
 
2138
 
#if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD)
2139
 
        os_mutex_enter(os_file_count_mutex);
2140
 
        os_file_n_pending_pwrites++;
2141
 
        os_n_pending_writes++;
2142
 
        os_mutex_exit(os_file_count_mutex);
2143
 
 
2144
 
        ret = pwrite(file, buf, (ssize_t)n, offs);
2145
 
 
2146
 
        os_mutex_enter(os_file_count_mutex);
2147
 
        os_file_n_pending_pwrites--;
2148
 
        os_n_pending_writes--;
2149
 
        os_mutex_exit(os_file_count_mutex);
2150
 
 
2151
 
# ifdef UNIV_DO_FLUSH
2152
 
        if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC
2153
 
            && srv_unix_file_flush_method != SRV_UNIX_NOSYNC
2154
 
            && !os_do_not_call_flush_at_each_write) {
2155
 
 
2156
 
                /* Always do fsync to reduce the probability that when
2157
 
                the OS crashes, a database page is only partially
2158
 
                physically written to disk. */
2159
 
 
2160
 
                ut_a(TRUE == os_file_flush(file));
2161
 
        }
2162
 
# endif /* UNIV_DO_FLUSH */
2163
 
 
2164
 
        return(ret);
2165
 
#else
2166
 
        {
2167
 
                off_t   ret_offset;
2168
 
                ulint   i;
2169
 
 
2170
 
                os_mutex_enter(os_file_count_mutex);
2171
 
                os_n_pending_writes++;
2172
 
                os_mutex_exit(os_file_count_mutex);
2173
 
 
2174
 
                /* Protect the seek / write operation with a mutex */
2175
 
                i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2176
 
 
2177
 
                os_mutex_enter(os_file_seek_mutexes[i]);
2178
 
 
2179
 
                ret_offset = lseek(file, offs, SEEK_SET);
2180
 
 
2181
 
                if (ret_offset < 0) {
2182
 
                        ret = -1;
2183
 
 
2184
 
                        goto func_exit;
2185
 
                }
2186
 
 
2187
 
                ret = write(file, buf, (ssize_t)n);
2188
 
 
2189
 
# ifdef UNIV_DO_FLUSH
2190
 
                if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC
2191
 
                    && srv_unix_file_flush_method != SRV_UNIX_NOSYNC
2192
 
                    && !os_do_not_call_flush_at_each_write) {
2193
 
 
2194
 
                        /* Always do fsync to reduce the probability that when
2195
 
                        the OS crashes, a database page is only partially
2196
 
                        physically written to disk. */
2197
 
 
2198
 
                        ut_a(TRUE == os_file_flush(file));
2199
 
                }
2200
 
# endif /* UNIV_DO_FLUSH */
2201
 
 
2202
 
func_exit:
2203
 
                os_mutex_exit(os_file_seek_mutexes[i]);
2204
 
 
2205
 
                os_mutex_enter(os_file_count_mutex);
2206
 
                os_n_pending_writes--;
2207
 
                os_mutex_exit(os_file_count_mutex);
2208
 
 
2209
 
                return(ret);
2210
 
        }
2211
 
#endif
2212
 
}
2213
 
#endif
2214
 
 
2215
 
/*******************************************************************//**
2216
 
Requests a synchronous positioned read operation.
2217
 
@return TRUE if request was successful, FALSE if fail */
2218
 
UNIV_INTERN
2219
 
ibool
2220
 
os_file_read(
2221
 
/*=========*/
2222
 
        os_file_t       file,   /*!< in: handle to a file */
2223
 
        void*           buf,    /*!< in: buffer where to read */
2224
 
        ulint           offset, /*!< in: least significant 32 bits of file
2225
 
                                offset where to read */
2226
 
        ulint           offset_high, /*!< in: most significant 32 bits of
2227
 
                                offset */
2228
 
        ulint           n)      /*!< in: number of bytes to read */
2229
 
{
2230
 
#ifdef __WIN__
2231
 
        BOOL            ret;
2232
 
        DWORD           len;
2233
 
        DWORD           ret2;
2234
 
        DWORD           low;
2235
 
        DWORD           high;
2236
 
        ibool           retry;
2237
 
        ulint           i;
2238
 
 
2239
 
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2240
 
 
2241
 
        os_n_file_reads++;
2242
 
        os_bytes_read_since_printout += n;
2243
 
 
2244
 
try_again:
2245
 
        ut_ad(file);
2246
 
        ut_ad(buf);
2247
 
        ut_ad(n > 0);
2248
 
 
2249
 
        low = (DWORD) offset;
2250
 
        high = (DWORD) offset_high;
2251
 
 
2252
 
        os_mutex_enter(os_file_count_mutex);
2253
 
        os_n_pending_reads++;
2254
 
        os_mutex_exit(os_file_count_mutex);
2255
 
 
2256
 
        /* Protect the seek / read operation with a mutex */
2257
 
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2258
 
 
2259
 
        os_mutex_enter(os_file_seek_mutexes[i]);
2260
 
 
2261
 
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2262
 
 
2263
 
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2264
 
 
2265
 
                os_mutex_exit(os_file_seek_mutexes[i]);
2266
 
 
2267
 
                os_mutex_enter(os_file_count_mutex);
2268
 
                os_n_pending_reads--;
2269
 
                os_mutex_exit(os_file_count_mutex);
2270
 
 
2271
 
                goto error_handling;
2272
 
        }
2273
 
 
2274
 
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
2275
 
 
2276
 
        os_mutex_exit(os_file_seek_mutexes[i]);
2277
 
 
2278
 
        os_mutex_enter(os_file_count_mutex);
2279
 
        os_n_pending_reads--;
2280
 
        os_mutex_exit(os_file_count_mutex);
2281
 
 
2282
 
        if (ret && len == n) {
2283
 
                return(TRUE);
2284
 
        }
2285
 
#else
2286
 
        ibool   retry;
2287
 
        ssize_t ret;
2288
 
 
2289
 
        os_bytes_read_since_printout += n;
2290
 
 
2291
 
try_again:
2292
 
        ret = os_file_pread(file, buf, n, offset, offset_high);
2293
 
 
2294
 
        if ((ulint)ret == n) {
2295
 
 
2296
 
                return(TRUE);
2297
 
        }
2298
 
 
2299
 
        fprintf(stderr,
2300
 
                "InnoDB: Error: tried to read %lu bytes at offset %lu %lu.\n"
2301
 
                "InnoDB: Was only able to read %ld.\n",
2302
 
                (ulong)n, (ulong)offset_high,
2303
 
                (ulong)offset, (long)ret);
2304
 
#endif
2305
 
#ifdef __WIN__
2306
 
error_handling:
2307
 
#endif
2308
 
        retry = os_file_handle_error(NULL, "read");
2309
 
 
2310
 
        if (retry) {
2311
 
                goto try_again;
2312
 
        }
2313
 
 
2314
 
        fprintf(stderr,
2315
 
                "InnoDB: Fatal error: cannot read from file."
2316
 
                " OS error number %lu.\n",
2317
 
#ifdef __WIN__
2318
 
                (ulong) GetLastError()
2319
 
#else
2320
 
                (ulong) errno
2321
 
#endif
2322
 
                );
2323
 
        fflush(stderr);
2324
 
 
2325
 
        ut_error;
2326
 
 
2327
 
        return(FALSE);
2328
 
}
2329
 
 
2330
 
/*******************************************************************//**
2331
 
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 */
2334
 
UNIV_INTERN
2335
 
ibool
2336
 
os_file_read_no_error_handling(
2337
 
/*===========================*/
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
2341
 
                                offset where to read */
2342
 
        ulint           offset_high, /*!< in: most significant 32 bits of
2343
 
                                offset */
2344
 
        ulint           n)      /*!< in: number of bytes to read */
2345
 
{
2346
 
#ifdef __WIN__
2347
 
        BOOL            ret;
2348
 
        DWORD           len;
2349
 
        DWORD           ret2;
2350
 
        DWORD           low;
2351
 
        DWORD           high;
2352
 
        ibool           retry;
2353
 
        ulint           i;
2354
 
 
2355
 
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2356
 
 
2357
 
        os_n_file_reads++;
2358
 
        os_bytes_read_since_printout += n;
2359
 
 
2360
 
try_again:
2361
 
        ut_ad(file);
2362
 
        ut_ad(buf);
2363
 
        ut_ad(n > 0);
2364
 
 
2365
 
        low = (DWORD) offset;
2366
 
        high = (DWORD) offset_high;
2367
 
 
2368
 
        os_mutex_enter(os_file_count_mutex);
2369
 
        os_n_pending_reads++;
2370
 
        os_mutex_exit(os_file_count_mutex);
2371
 
 
2372
 
        /* Protect the seek / read operation with a mutex */
2373
 
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2374
 
 
2375
 
        os_mutex_enter(os_file_seek_mutexes[i]);
2376
 
 
2377
 
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2378
 
 
2379
 
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2380
 
 
2381
 
                os_mutex_exit(os_file_seek_mutexes[i]);
2382
 
 
2383
 
                os_mutex_enter(os_file_count_mutex);
2384
 
                os_n_pending_reads--;
2385
 
                os_mutex_exit(os_file_count_mutex);
2386
 
 
2387
 
                goto error_handling;
2388
 
        }
2389
 
 
2390
 
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
2391
 
 
2392
 
        os_mutex_exit(os_file_seek_mutexes[i]);
2393
 
 
2394
 
        os_mutex_enter(os_file_count_mutex);
2395
 
        os_n_pending_reads--;
2396
 
        os_mutex_exit(os_file_count_mutex);
2397
 
 
2398
 
        if (ret && len == n) {
2399
 
                return(TRUE);
2400
 
        }
2401
 
#else
2402
 
        ibool   retry;
2403
 
        ssize_t ret;
2404
 
 
2405
 
        os_bytes_read_since_printout += n;
2406
 
 
2407
 
try_again:
2408
 
        ret = os_file_pread(file, buf, n, offset, offset_high);
2409
 
 
2410
 
        if ((ulint)ret == n) {
2411
 
 
2412
 
                return(TRUE);
2413
 
        }
2414
 
#endif
2415
 
#ifdef __WIN__
2416
 
error_handling:
2417
 
#endif
2418
 
        retry = os_file_handle_error_no_exit(NULL, "read");
2419
 
 
2420
 
        if (retry) {
2421
 
                goto try_again;
2422
 
        }
2423
 
 
2424
 
        return(FALSE);
2425
 
}
2426
 
 
2427
 
/*******************************************************************//**
2428
 
Rewind file to its start, read at most size - 1 bytes from it to str, and
2429
 
NUL-terminate str. All errors are silently ignored. This function is
2430
 
mostly meant to be used with temporary files. */
2431
 
UNIV_INTERN
2432
 
void
2433
 
os_file_read_string(
2434
 
/*================*/
2435
 
        FILE*   file,   /*!< in: file to read from */
2436
 
        char*   str,    /*!< in: buffer where to read */
2437
 
        ulint   size)   /*!< in: size of buffer */
2438
 
{
2439
 
        size_t  flen;
2440
 
 
2441
 
        if (size == 0) {
2442
 
                return;
2443
 
        }
2444
 
 
2445
 
        rewind(file);
2446
 
        flen = fread(str, 1, size - 1, file);
2447
 
        str[flen] = '\0';
2448
 
}
2449
 
 
2450
 
/*******************************************************************//**
2451
 
Requests a synchronous write operation.
2452
 
@return TRUE if request was successful, FALSE if fail */
2453
 
UNIV_INTERN
2454
 
ibool
2455
 
os_file_write(
2456
 
/*==========*/
2457
 
        const char*     name,   /*!< in: name of the file or path as a
2458
 
                                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
2462
 
                                offset where to write */
2463
 
        ulint           offset_high, /*!< in: most significant 32 bits of
2464
 
                                offset */
2465
 
        ulint           n)      /*!< in: number of bytes to write */
2466
 
{
2467
 
#ifdef __WIN__
2468
 
        BOOL            ret;
2469
 
        DWORD           len;
2470
 
        DWORD           ret2;
2471
 
        DWORD           low;
2472
 
        DWORD           high;
2473
 
        ulint           i;
2474
 
        ulint           n_retries       = 0;
2475
 
        ulint           err;
2476
 
 
2477
 
        ut_a((offset & 0xFFFFFFFF) == offset);
2478
 
 
2479
 
        os_n_file_writes++;
2480
 
 
2481
 
        ut_ad(file);
2482
 
        ut_ad(buf);
2483
 
        ut_ad(n > 0);
2484
 
retry:
2485
 
        low = (DWORD) offset;
2486
 
        high = (DWORD) offset_high;
2487
 
 
2488
 
        os_mutex_enter(os_file_count_mutex);
2489
 
        os_n_pending_writes++;
2490
 
        os_mutex_exit(os_file_count_mutex);
2491
 
 
2492
 
        /* Protect the seek / write operation with a mutex */
2493
 
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2494
 
 
2495
 
        os_mutex_enter(os_file_seek_mutexes[i]);
2496
 
 
2497
 
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2498
 
 
2499
 
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2500
 
 
2501
 
                os_mutex_exit(os_file_seek_mutexes[i]);
2502
 
 
2503
 
                os_mutex_enter(os_file_count_mutex);
2504
 
                os_n_pending_writes--;
2505
 
                os_mutex_exit(os_file_count_mutex);
2506
 
 
2507
 
                ut_print_timestamp(stderr);
2508
 
 
2509
 
                fprintf(stderr,
2510
 
                        "  InnoDB: Error: File pointer positioning to"
2511
 
                        " file %s failed at\n"
2512
 
                        "InnoDB: offset %lu %lu. Operating system"
2513
 
                        " error number %lu.\n"
2514
 
                        "InnoDB: Some operating system error numbers"
2515
 
                        " are described at\n"
2516
 
                        "InnoDB: "
2517
 
                        REFMAN "operating-system-error-codes.html\n",
2518
 
                        name, (ulong) offset_high, (ulong) offset,
2519
 
                        (ulong) GetLastError());
2520
 
 
2521
 
                return(FALSE);
2522
 
        }
2523
 
 
2524
 
        ret = WriteFile(file, buf, (DWORD) n, &len, NULL);
2525
 
 
2526
 
        /* Always do fsync to reduce the probability that when the OS crashes,
2527
 
        a database page is only partially physically written to disk. */
2528
 
 
2529
 
# ifdef UNIV_DO_FLUSH
2530
 
        if (!os_do_not_call_flush_at_each_write) {
2531
 
                ut_a(TRUE == os_file_flush(file));
2532
 
        }
2533
 
# endif /* UNIV_DO_FLUSH */
2534
 
 
2535
 
        os_mutex_exit(os_file_seek_mutexes[i]);
2536
 
 
2537
 
        os_mutex_enter(os_file_count_mutex);
2538
 
        os_n_pending_writes--;
2539
 
        os_mutex_exit(os_file_count_mutex);
2540
 
 
2541
 
        if (ret && len == n) {
2542
 
 
2543
 
                return(TRUE);
2544
 
        }
2545
 
 
2546
 
        /* If some background file system backup tool is running, then, at
2547
 
        least in Windows 2000, we may get here a specific error. Let us
2548
 
        retry the operation 100 times, with 1 second waits. */
2549
 
 
2550
 
        if (GetLastError() == ERROR_LOCK_VIOLATION && n_retries < 100) {
2551
 
 
2552
 
                os_thread_sleep(1000000);
2553
 
 
2554
 
                n_retries++;
2555
 
 
2556
 
                goto retry;
2557
 
        }
2558
 
 
2559
 
        if (!os_has_said_disk_full) {
2560
 
 
2561
 
                err = (ulint)GetLastError();
2562
 
 
2563
 
                ut_print_timestamp(stderr);
2564
 
 
2565
 
                fprintf(stderr,
2566
 
                        "  InnoDB: Error: Write to file %s failed"
2567
 
                        " at offset %lu %lu.\n"
2568
 
                        "InnoDB: %lu bytes should have been written,"
2569
 
                        " only %lu were written.\n"
2570
 
                        "InnoDB: Operating system error number %lu.\n"
2571
 
                        "InnoDB: Check that your OS and file system"
2572
 
                        " support files of this size.\n"
2573
 
                        "InnoDB: Check also that the disk is not full"
2574
 
                        " or a disk quota exceeded.\n",
2575
 
                        name, (ulong) offset_high, (ulong) offset,
2576
 
                        (ulong) n, (ulong) len, (ulong) err);
2577
 
 
2578
 
                if (strerror((int)err) != NULL) {
2579
 
                        fprintf(stderr,
2580
 
                                "InnoDB: Error number %lu means '%s'.\n",
2581
 
                                (ulong) err, strerror((int)err));
2582
 
                }
2583
 
 
2584
 
                fprintf(stderr,
2585
 
                        "InnoDB: Some operating system error numbers"
2586
 
                        " are described at\n"
2587
 
                        "InnoDB: "
2588
 
                        REFMAN "operating-system-error-codes.html\n");
2589
 
 
2590
 
                os_has_said_disk_full = TRUE;
2591
 
        }
2592
 
 
2593
 
        return(FALSE);
2594
 
#else
2595
 
        ssize_t ret;
2596
 
 
2597
 
        ret = os_file_pwrite(file, buf, n, offset, offset_high);
2598
 
 
2599
 
        if ((ulint)ret == n) {
2600
 
 
2601
 
                return(TRUE);
2602
 
        }
2603
 
 
2604
 
        if (!os_has_said_disk_full) {
2605
 
 
2606
 
                ut_print_timestamp(stderr);
2607
 
 
2608
 
                fprintf(stderr,
2609
 
                        "  InnoDB: Error: Write to file %s failed"
2610
 
                        " at offset %lu %lu.\n"
2611
 
                        "InnoDB: %lu bytes should have been written,"
2612
 
                        " only %ld were written.\n"
2613
 
                        "InnoDB: Operating system error number %lu.\n"
2614
 
                        "InnoDB: Check that your OS and file system"
2615
 
                        " support files of this size.\n"
2616
 
                        "InnoDB: Check also that the disk is not full"
2617
 
                        " or a disk quota exceeded.\n",
2618
 
                        name, offset_high, offset, n, (long int)ret,
2619
 
                        (ulint)errno);
2620
 
                if (strerror(errno) != NULL) {
2621
 
                        fprintf(stderr,
2622
 
                                "InnoDB: Error number %lu means '%s'.\n",
2623
 
                                (ulint)errno, strerror(errno));
2624
 
                }
2625
 
 
2626
 
                fprintf(stderr,
2627
 
                        "InnoDB: Some operating system error numbers"
2628
 
                        " are described at\n"
2629
 
                        "InnoDB: "
2630
 
                        REFMAN "operating-system-error-codes.html\n");
2631
 
 
2632
 
                os_has_said_disk_full = TRUE;
2633
 
        }
2634
 
 
2635
 
        return(FALSE);
2636
 
#endif
2637
 
}
2638
 
 
2639
 
/*******************************************************************//**
2640
 
Check the existence and type of the given file.
2641
 
@return TRUE if call succeeded */
2642
 
UNIV_INTERN
2643
 
ibool
2644
 
os_file_status(
2645
 
/*===========*/
2646
 
        const char*     path,   /*!< in:        pathname of the file */
2647
 
        ibool*          exists, /*!< out: TRUE if file exists */
2648
 
        os_file_type_t* type)   /*!< out: type of the file (if it exists) */
2649
 
{
2650
 
#ifdef __WIN__
2651
 
        int             ret;
2652
 
        struct _stat    statinfo;
2653
 
 
2654
 
        ret = _stat(path, &statinfo);
2655
 
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
2656
 
                /* file does not exist */
2657
 
                *exists = FALSE;
2658
 
                return(TRUE);
2659
 
        } else if (ret) {
2660
 
                /* file exists, but stat call failed */
2661
 
 
2662
 
                os_file_handle_error_no_exit(path, "stat");
2663
 
 
2664
 
                return(FALSE);
2665
 
        }
2666
 
 
2667
 
        if (_S_IFDIR & statinfo.st_mode) {
2668
 
                *type = OS_FILE_TYPE_DIR;
2669
 
        } else if (_S_IFREG & statinfo.st_mode) {
2670
 
                *type = OS_FILE_TYPE_FILE;
2671
 
        } else {
2672
 
                *type = OS_FILE_TYPE_UNKNOWN;
2673
 
        }
2674
 
 
2675
 
        *exists = TRUE;
2676
 
 
2677
 
        return(TRUE);
2678
 
#else
2679
 
        int             ret;
2680
 
        struct stat     statinfo;
2681
 
 
2682
 
        ret = stat(path, &statinfo);
2683
 
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
2684
 
                /* file does not exist */
2685
 
                *exists = FALSE;
2686
 
                return(TRUE);
2687
 
        } else if (ret) {
2688
 
                /* file exists, but stat call failed */
2689
 
 
2690
 
                os_file_handle_error_no_exit(path, "stat");
2691
 
 
2692
 
                return(FALSE);
2693
 
        }
2694
 
 
2695
 
        if (S_ISDIR(statinfo.st_mode)) {
2696
 
                *type = OS_FILE_TYPE_DIR;
2697
 
        } else if (S_ISLNK(statinfo.st_mode)) {
2698
 
                *type = OS_FILE_TYPE_LINK;
2699
 
        } else if (S_ISREG(statinfo.st_mode)) {
2700
 
                *type = OS_FILE_TYPE_FILE;
2701
 
        } else {
2702
 
                *type = OS_FILE_TYPE_UNKNOWN;
2703
 
        }
2704
 
 
2705
 
        *exists = TRUE;
2706
 
 
2707
 
        return(TRUE);
2708
 
#endif
2709
 
}
2710
 
 
2711
 
/*******************************************************************//**
2712
 
This function returns information about the specified file
2713
 
@return TRUE if stat information found */
2714
 
UNIV_INTERN
2715
 
ibool
2716
 
os_file_get_status(
2717
 
/*===============*/
2718
 
        const char*     path,           /*!< in:        pathname of the file */
2719
 
        os_file_stat_t* stat_info)      /*!< information of a file in a
2720
 
                                        directory */
2721
 
{
2722
 
#ifdef __WIN__
2723
 
        int             ret;
2724
 
        struct _stat    statinfo;
2725
 
 
2726
 
        ret = _stat(path, &statinfo);
2727
 
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
2728
 
                /* file does not exist */
2729
 
 
2730
 
                return(FALSE);
2731
 
        } else if (ret) {
2732
 
                /* file exists, but stat call failed */
2733
 
 
2734
 
                os_file_handle_error_no_exit(path, "stat");
2735
 
 
2736
 
                return(FALSE);
2737
 
        }
2738
 
        if (_S_IFDIR & statinfo.st_mode) {
2739
 
                stat_info->type = OS_FILE_TYPE_DIR;
2740
 
        } else if (_S_IFREG & statinfo.st_mode) {
2741
 
                stat_info->type = OS_FILE_TYPE_FILE;
2742
 
        } else {
2743
 
                stat_info->type = OS_FILE_TYPE_UNKNOWN;
2744
 
        }
2745
 
 
2746
 
        stat_info->ctime = statinfo.st_ctime;
2747
 
        stat_info->atime = statinfo.st_atime;
2748
 
        stat_info->mtime = statinfo.st_mtime;
2749
 
        stat_info->size  = statinfo.st_size;
2750
 
 
2751
 
        return(TRUE);
2752
 
#else
2753
 
        int             ret;
2754
 
        struct stat     statinfo;
2755
 
 
2756
 
        ret = stat(path, &statinfo);
2757
 
 
2758
 
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
2759
 
                /* file does not exist */
2760
 
 
2761
 
                return(FALSE);
2762
 
        } else if (ret) {
2763
 
                /* file exists, but stat call failed */
2764
 
 
2765
 
                os_file_handle_error_no_exit(path, "stat");
2766
 
 
2767
 
                return(FALSE);
2768
 
        }
2769
 
 
2770
 
        if (S_ISDIR(statinfo.st_mode)) {
2771
 
                stat_info->type = OS_FILE_TYPE_DIR;
2772
 
        } else if (S_ISLNK(statinfo.st_mode)) {
2773
 
                stat_info->type = OS_FILE_TYPE_LINK;
2774
 
        } else if (S_ISREG(statinfo.st_mode)) {
2775
 
                stat_info->type = OS_FILE_TYPE_FILE;
2776
 
        } else {
2777
 
                stat_info->type = OS_FILE_TYPE_UNKNOWN;
2778
 
        }
2779
 
 
2780
 
        stat_info->ctime = statinfo.st_ctime;
2781
 
        stat_info->atime = statinfo.st_atime;
2782
 
        stat_info->mtime = statinfo.st_mtime;
2783
 
        stat_info->size  = statinfo.st_size;
2784
 
 
2785
 
        return(TRUE);
2786
 
#endif
2787
 
}
2788
 
 
2789
 
/* path name separator character */
2790
 
#ifdef __WIN__
2791
 
#  define OS_FILE_PATH_SEPARATOR        '\\'
2792
 
#else
2793
 
#  define OS_FILE_PATH_SEPARATOR        '/'
2794
 
#endif
2795
 
 
2796
 
/****************************************************************//**
2797
 
The function os_file_dirname returns a directory component of a
2798
 
null-terminated pathname string.  In the usual case, dirname returns
2799
 
the string up to, but not including, the final '/', and basename
2800
 
is the component following the final '/'.  Trailing '/' characļæ½
2801
 
ters are not counted as part of the pathname.
2802
 
 
2803
 
If path does not contain a slash, dirname returns the string ".".
2804
 
 
2805
 
Concatenating the string returned by dirname, a "/", and the basename
2806
 
yields a complete pathname.
2807
 
 
2808
 
The return value is  a copy of the directory component of the pathname.
2809
 
The copy is allocated from heap. It is the caller responsibility
2810
 
to free it after it is no longer needed.
2811
 
 
2812
 
The following list of examples (taken from SUSv2) shows the strings
2813
 
returned by dirname and basename for different paths:
2814
 
 
2815
 
       path           dirname        basename
2816
 
       "/usr/lib"     "/usr"         "lib"
2817
 
       "/usr/"        "/"            "usr"
2818
 
       "usr"          "."            "usr"
2819
 
       "/"            "/"            "/"
2820
 
       "."            "."            "."
2821
 
       ".."           "."            ".."
2822
 
 
2823
 
@return own: directory component of the pathname */
2824
 
UNIV_INTERN
2825
 
char*
2826
 
os_file_dirname(
2827
 
/*============*/
2828
 
        const char*     path)   /*!< in: pathname */
2829
 
{
2830
 
        /* Find the offset of the last slash */
2831
 
        const char* last_slash = strrchr(path, OS_FILE_PATH_SEPARATOR);
2832
 
        if (!last_slash) {
2833
 
                /* No slash in the path, return "." */
2834
 
 
2835
 
                return(mem_strdup("."));
2836
 
        }
2837
 
 
2838
 
        /* Ok, there is a slash */
2839
 
 
2840
 
        if (last_slash == path) {
2841
 
                /* last slash is the first char of the path */
2842
 
 
2843
 
                return(mem_strdup("/"));
2844
 
        }
2845
 
 
2846
 
        /* Non-trivial directory component */
2847
 
 
2848
 
        return(mem_strdupl(path, last_slash - path));
2849
 
}
2850
 
 
2851
 
/****************************************************************//**
2852
 
Creates all missing subdirectories along the given path.
2853
 
@return TRUE if call succeeded FALSE otherwise */
2854
 
UNIV_INTERN
2855
 
ibool
2856
 
os_file_create_subdirs_if_needed(
2857
 
/*=============================*/
2858
 
        const char*     path)   /*!< in: path name */
2859
 
{
2860
 
        char*           subdir;
2861
 
        ibool           success, subdir_exists;
2862
 
        os_file_type_t  type;
2863
 
 
2864
 
        subdir = os_file_dirname(path);
2865
 
        if (strlen(subdir) == 1
2866
 
            && (*subdir == OS_FILE_PATH_SEPARATOR || *subdir == '.')) {
2867
 
                /* subdir is root or cwd, nothing to do */
2868
 
                mem_free(subdir);
2869
 
 
2870
 
                return(TRUE);
2871
 
        }
2872
 
 
2873
 
        /* Test if subdir exists */
2874
 
        success = os_file_status(subdir, &subdir_exists, &type);
2875
 
        if (success && !subdir_exists) {
2876
 
                /* subdir does not exist, create it */
2877
 
                success = os_file_create_subdirs_if_needed(subdir);
2878
 
                if (!success) {
2879
 
                        mem_free(subdir);
2880
 
 
2881
 
                        return(FALSE);
2882
 
                }
2883
 
                success = os_file_create_directory(subdir, FALSE);
2884
 
        }
2885
 
 
2886
 
        mem_free(subdir);
2887
 
 
2888
 
        return(success);
2889
 
}
2890
 
 
2891
 
#ifndef UNIV_HOTBACKUP
2892
 
/****************************************************************//**
2893
 
Returns a pointer to the nth slot in the aio array.
2894
 
@return pointer to slot */
2895
 
static
2896
 
os_aio_slot_t*
2897
 
os_aio_array_get_nth_slot(
2898
 
/*======================*/
2899
 
        os_aio_array_t*         array,  /*!< in: aio array */
2900
 
        ulint                   index)  /*!< in: index of the slot */
2901
 
{
2902
 
        ut_a(index < array->n_slots);
2903
 
 
2904
 
        return((array->slots) + index);
2905
 
}
2906
 
 
2907
 
/************************************************************************//**
2908
 
Creates an aio wait array.
2909
 
@return own: aio array */
2910
 
static
2911
 
os_aio_array_t*
2912
 
os_aio_array_create(
2913
 
/*================*/
2914
 
        ulint   n,              /*!< in: maximum number of pending aio operations
2915
 
                                allowed; n must be divisible by n_segments */
2916
 
        ulint   n_segments)     /*!< in: number of segments in the aio array */
2917
 
{
2918
 
        os_aio_array_t* array;
2919
 
        ulint           i;
2920
 
        os_aio_slot_t*  slot;
2921
 
#ifdef WIN_ASYNC_IO
2922
 
        OVERLAPPED*     over;
2923
 
#endif
2924
 
        ut_a(n > 0);
2925
 
        ut_a(n_segments > 0);
2926
 
 
2927
 
        array = ut_malloc(sizeof(os_aio_array_t));
2928
 
 
2929
 
        array->mutex            = os_mutex_create(NULL);
2930
 
        array->not_full         = os_event_create(NULL);
2931
 
        array->is_empty         = os_event_create(NULL);
2932
 
 
2933
 
        os_event_set(array->is_empty);
2934
 
 
2935
 
        array->n_slots          = n;
2936
 
        array->n_segments       = n_segments;
2937
 
        array->n_reserved       = 0;
2938
 
        array->slots            = ut_malloc(n * sizeof(os_aio_slot_t));
2939
 
#ifdef __WIN__
2940
 
        array->native_events    = ut_malloc(n * sizeof(os_native_event_t));
2941
 
#endif
2942
 
        for (i = 0; i < n; i++) {
2943
 
                slot = os_aio_array_get_nth_slot(array, i);
2944
 
 
2945
 
                slot->pos = i;
2946
 
                slot->reserved = FALSE;
2947
 
#ifdef WIN_ASYNC_IO
2948
 
                slot->event = os_event_create(NULL);
2949
 
 
2950
 
                over = &(slot->control);
2951
 
 
2952
 
                over->hEvent = slot->event->handle;
2953
 
 
2954
 
                *((array->native_events) + i) = over->hEvent;
2955
 
#endif
2956
 
        }
2957
 
 
2958
 
        return(array);
2959
 
}
2960
 
 
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 */
2968
 
UNIV_INTERN
2969
 
void
2970
 
os_aio_init(
2971
 
/*========*/
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
2977
 
                                array */
2978
 
{
2979
 
        ulint   i;
2980
 
        ulint   n_segments = 2 + n_read_segs + n_write_segs;
2981
 
 
2982
 
        ut_ad(n_segments >= 4);
2983
 
 
2984
 
        os_io_init_simple();
2985
 
 
2986
 
        for (i = 0; i < n_segments; i++) {
2987
 
                srv_set_io_thread_op_info(i, "not started yet");
2988
 
        }
2989
 
 
2990
 
 
2991
 
        /* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
2992
 
 
2993
 
        os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1);
2994
 
 
2995
 
        srv_io_thread_function[0] = "insert buffer thread";
2996
 
 
2997
 
        os_aio_log_array = os_aio_array_create(n_per_seg, 1);
2998
 
 
2999
 
        srv_io_thread_function[1] = "log thread";
3000
 
 
3001
 
        os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
3002
 
                                                n_read_segs);
3003
 
        for (i = 2; i < 2 + n_read_segs; i++) {
3004
 
                ut_a(i < SRV_MAX_N_IO_THREADS);
3005
 
                srv_io_thread_function[i] = "read thread";
3006
 
        }
3007
 
 
3008
 
        os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
3009
 
                                                 n_write_segs);
3010
 
        for (i = 2 + n_read_segs; i < n_segments; i++) {
3011
 
                ut_a(i < SRV_MAX_N_IO_THREADS);
3012
 
                srv_io_thread_function[i] = "write thread";
3013
 
        }
3014
 
 
3015
 
        os_aio_sync_array = os_aio_array_create(n_slots_sync, 1);
3016
 
 
3017
 
        os_aio_n_segments = n_segments;
3018
 
 
3019
 
        os_aio_validate();
3020
 
 
3021
 
        os_aio_segment_wait_events = ut_malloc(n_segments * sizeof(void*));
3022
 
 
3023
 
        for (i = 0; i < n_segments; i++) {
3024
 
                os_aio_segment_wait_events[i] = os_event_create(NULL);
3025
 
        }
3026
 
 
3027
 
        os_last_printout = time(NULL);
3028
 
 
3029
 
}
3030
 
 
3031
 
#ifdef WIN_ASYNC_IO
3032
 
/************************************************************************//**
3033
 
Wakes up all async i/o threads in the array in Windows async i/o at
3034
 
shutdown. */
3035
 
static
3036
 
void
3037
 
os_aio_array_wake_win_aio_at_shutdown(
3038
 
/*==================================*/
3039
 
        os_aio_array_t* array)  /*!< in: aio array */
3040
 
{
3041
 
        ulint   i;
3042
 
 
3043
 
        for (i = 0; i < array->n_slots; i++) {
3044
 
 
3045
 
                os_event_set((array->slots + i)->event);
3046
 
        }
3047
 
}
3048
 
#endif
3049
 
 
3050
 
/************************************************************************//**
3051
 
Wakes up all async i/o threads so that they know to exit themselves in
3052
 
shutdown. */
3053
 
UNIV_INTERN
3054
 
void
3055
 
os_aio_wake_all_threads_at_shutdown(void)
3056
 
/*=====================================*/
3057
 
{
3058
 
        ulint   i;
3059
 
 
3060
 
#ifdef WIN_ASYNC_IO
3061
 
        /* This code wakes up all ai/o threads in Windows native aio */
3062
 
        os_aio_array_wake_win_aio_at_shutdown(os_aio_read_array);
3063
 
        os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
3064
 
        os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
3065
 
        os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array);
3066
 
#endif
3067
 
        /* This loop wakes up all simulated ai/o threads */
3068
 
 
3069
 
        for (i = 0; i < os_aio_n_segments; i++) {
3070
 
 
3071
 
                os_event_set(os_aio_segment_wait_events[i]);
3072
 
        }
3073
 
}
3074
 
 
3075
 
/************************************************************************//**
3076
 
Waits until there are no pending writes in os_aio_write_array. There can
3077
 
be other, synchronous, pending writes. */
3078
 
UNIV_INTERN
3079
 
void
3080
 
os_aio_wait_until_no_pending_writes(void)
3081
 
/*=====================================*/
3082
 
{
3083
 
        os_event_wait(os_aio_write_array->is_empty);
3084
 
}
3085
 
 
3086
 
/**********************************************************************//**
3087
 
Calculates segment number for a slot.
3088
 
@return segment number (which is the number used by, for example,
3089
 
i/o-handler threads) */
3090
 
static
3091
 
ulint
3092
 
os_aio_get_segment_no_from_slot(
3093
 
/*============================*/
3094
 
        os_aio_array_t* array,  /*!< in: aio wait array */
3095
 
        os_aio_slot_t*  slot)   /*!< in: slot in this array */
3096
 
{
3097
 
        ulint   segment;
3098
 
        ulint   seg_len;
3099
 
 
3100
 
        if (array == os_aio_ibuf_array) {
3101
 
                segment = 0;
3102
 
 
3103
 
        } else if (array == os_aio_log_array) {
3104
 
                segment = 1;
3105
 
 
3106
 
        } else if (array == os_aio_read_array) {
3107
 
                seg_len = os_aio_read_array->n_slots
3108
 
                        / os_aio_read_array->n_segments;
3109
 
 
3110
 
                segment = 2 + slot->pos / seg_len;
3111
 
        } else {
3112
 
                ut_a(array == os_aio_write_array);
3113
 
                seg_len = os_aio_write_array->n_slots
3114
 
                        / os_aio_write_array->n_segments;
3115
 
 
3116
 
                segment = os_aio_read_array->n_segments + 2
3117
 
                        + slot->pos / seg_len;
3118
 
        }
3119
 
 
3120
 
        return(segment);
3121
 
}
3122
 
 
3123
 
/**********************************************************************//**
3124
 
Calculates local segment number and aio array from global segment number.
3125
 
@return local segment number within the aio array */
3126
 
static
3127
 
ulint
3128
 
os_aio_get_array_and_local_segment(
3129
 
/*===============================*/
3130
 
        os_aio_array_t** array,         /*!< out: aio wait array */
3131
 
        ulint            global_segment)/*!< in: global segment number */
3132
 
{
3133
 
        ulint   segment;
3134
 
 
3135
 
        ut_a(global_segment < os_aio_n_segments);
3136
 
 
3137
 
        if (global_segment == 0) {
3138
 
                *array = os_aio_ibuf_array;
3139
 
                segment = 0;
3140
 
 
3141
 
        } else if (global_segment == 1) {
3142
 
                *array = os_aio_log_array;
3143
 
                segment = 0;
3144
 
 
3145
 
        } else if (global_segment < os_aio_read_array->n_segments + 2) {
3146
 
                *array = os_aio_read_array;
3147
 
 
3148
 
                segment = global_segment - 2;
3149
 
        } else {
3150
 
                *array = os_aio_write_array;
3151
 
 
3152
 
                segment = global_segment - (os_aio_read_array->n_segments + 2);
3153
 
        }
3154
 
 
3155
 
        return(segment);
3156
 
}
3157
 
 
3158
 
/*******************************************************************//**
3159
 
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 */
3162
 
static
3163
 
os_aio_slot_t*
3164
 
os_aio_array_reserve_slot(
3165
 
/*======================*/
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
3174
 
                                null-terminated string */
3175
 
        void*           buf,    /*!< in: buffer where to read or from which
3176
 
                                to write */
3177
 
        ulint           offset, /*!< in: least significant 32 bits of file
3178
 
                                offset */
3179
 
        ulint           offset_high, /*!< in: most significant 32 bits of
3180
 
                                offset */
3181
 
        ulint           len)    /*!< in: length of the block to read or write */
3182
 
{
3183
 
        os_aio_slot_t*  slot;
3184
 
#ifdef WIN_ASYNC_IO
3185
 
        OVERLAPPED*     control;
3186
 
#endif
3187
 
        ulint           i;
3188
 
        ulint           slots_per_seg;
3189
 
        ulint           local_seg;
3190
 
 
3191
 
        /* No need of a mutex. Only reading constant fields */
3192
 
        slots_per_seg = array->n_slots / array->n_segments;
3193
 
 
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;
3199
 
 
3200
 
loop:
3201
 
        os_mutex_enter(array->mutex);
3202
 
 
3203
 
        if (array->n_reserved == array->n_slots) {
3204
 
                os_mutex_exit(array->mutex);
3205
 
 
3206
 
                if (!os_aio_use_native_aio) {
3207
 
                        /* If the handler threads are suspended, wake them
3208
 
                        so that we get more slots */
3209
 
 
3210
 
                        os_aio_simulated_wake_handler_threads();
3211
 
                }
3212
 
 
3213
 
                os_event_wait(array->not_full);
3214
 
 
3215
 
                goto loop;
3216
 
        }
3217
 
 
3218
 
        /* First try to find a slot in the preferred local segment */
3219
 
        for (i = local_seg * slots_per_seg; i < array->n_slots; i++) {
3220
 
                slot = os_aio_array_get_nth_slot(array, i);
3221
 
 
3222
 
                if (slot->reserved == FALSE) {
3223
 
                        goto found;
3224
 
                }
3225
 
        }
3226
 
 
3227
 
        /* Fall back to a full scan. We are guaranteed to find a slot */
3228
 
        for (i = 0;; i++) {
3229
 
                slot = os_aio_array_get_nth_slot(array, i);
3230
 
 
3231
 
                if (slot->reserved == FALSE) {
3232
 
                        goto found;
3233
 
                }
3234
 
        }
3235
 
 
3236
 
found:
3237
 
        ut_a(slot->reserved == FALSE);
3238
 
        array->n_reserved++;
3239
 
 
3240
 
        if (array->n_reserved == 1) {
3241
 
                os_event_reset(array->is_empty);
3242
 
        }
3243
 
 
3244
 
        if (array->n_reserved == array->n_slots) {
3245
 
                os_event_reset(array->not_full);
3246
 
        }
3247
 
 
3248
 
        slot->reserved = TRUE;
3249
 
        slot->reservation_time = time(NULL);
3250
 
        slot->message1 = message1;
3251
 
        slot->message2 = message2;
3252
 
        slot->file     = file;
3253
 
        slot->name     = name;
3254
 
        slot->len      = len;
3255
 
        slot->type     = type;
3256
 
        slot->buf      = buf;
3257
 
        slot->offset   = offset;
3258
 
        slot->offset_high = offset_high;
3259
 
        slot->io_already_done = FALSE;
3260
 
 
3261
 
#ifdef WIN_ASYNC_IO
3262
 
        control = &(slot->control);
3263
 
        control->Offset = (DWORD)offset;
3264
 
        control->OffsetHigh = (DWORD)offset_high;
3265
 
        os_event_reset(slot->event);
3266
 
#endif
3267
 
 
3268
 
        os_mutex_exit(array->mutex);
3269
 
 
3270
 
        return(slot);
3271
 
}
3272
 
 
3273
 
/*******************************************************************//**
3274
 
Frees a slot in the aio array. */
3275
 
static
3276
 
void
3277
 
os_aio_array_free_slot(
3278
 
/*===================*/
3279
 
        os_aio_array_t* array,  /*!< in: aio array */
3280
 
        os_aio_slot_t*  slot)   /*!< in: pointer to slot */
3281
 
{
3282
 
        ut_ad(array);
3283
 
        ut_ad(slot);
3284
 
 
3285
 
        os_mutex_enter(array->mutex);
3286
 
 
3287
 
        ut_ad(slot->reserved);
3288
 
 
3289
 
        slot->reserved = FALSE;
3290
 
 
3291
 
        array->n_reserved--;
3292
 
 
3293
 
        if (array->n_reserved == array->n_slots - 1) {
3294
 
                os_event_set(array->not_full);
3295
 
        }
3296
 
 
3297
 
        if (array->n_reserved == 0) {
3298
 
                os_event_set(array->is_empty);
3299
 
        }
3300
 
 
3301
 
#ifdef WIN_ASYNC_IO
3302
 
        os_event_reset(slot->event);
3303
 
#endif
3304
 
        os_mutex_exit(array->mutex);
3305
 
}
3306
 
 
3307
 
/**********************************************************************//**
3308
 
Wakes up a simulated aio i/o-handler thread if it has something to do. */
3309
 
static
3310
 
void
3311
 
os_aio_simulated_wake_handler_thread(
3312
 
/*=================================*/
3313
 
        ulint   global_segment) /*!< in: the number of the segment in the aio
3314
 
                                arrays */
3315
 
{
3316
 
        os_aio_array_t* array;
3317
 
        os_aio_slot_t*  slot;
3318
 
        ulint           segment;
3319
 
        ulint           n;
3320
 
        ulint           i;
3321
 
 
3322
 
        ut_ad(!os_aio_use_native_aio);
3323
 
 
3324
 
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
3325
 
 
3326
 
        n = array->n_slots / array->n_segments;
3327
 
 
3328
 
        /* Look through n slots after the segment * n'th slot */
3329
 
 
3330
 
        os_mutex_enter(array->mutex);
3331
 
 
3332
 
        for (i = 0; i < n; i++) {
3333
 
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
3334
 
 
3335
 
                if (slot->reserved) {
3336
 
                        /* Found an i/o request */
3337
 
 
3338
 
                        break;
3339
 
                }
3340
 
        }
3341
 
 
3342
 
        os_mutex_exit(array->mutex);
3343
 
 
3344
 
        if (i < n) {
3345
 
                os_event_set(os_aio_segment_wait_events[global_segment]);
3346
 
        }
3347
 
}
3348
 
 
3349
 
/**********************************************************************//**
3350
 
Wakes up simulated aio i/o-handler threads if they have something to do. */
3351
 
UNIV_INTERN
3352
 
void
3353
 
os_aio_simulated_wake_handler_threads(void)
3354
 
/*=======================================*/
3355
 
{
3356
 
        ulint   i;
3357
 
 
3358
 
        if (os_aio_use_native_aio) {
3359
 
                /* We do not use simulated aio: do nothing */
3360
 
 
3361
 
                return;
3362
 
        }
3363
 
 
3364
 
        os_aio_recommend_sleep_for_read_threads = FALSE;
3365
 
 
3366
 
        for (i = 0; i < os_aio_n_segments; i++) {
3367
 
                os_aio_simulated_wake_handler_thread(i);
3368
 
        }
3369
 
}
3370
 
 
3371
 
/**********************************************************************//**
3372
 
This function can be called if one wants to post a batch of reads and
3373
 
prefers an i/o-handler thread to handle them all at once later. You must
3374
 
call os_aio_simulated_wake_handler_threads later to ensure the threads
3375
 
are not left sleeping! */
3376
 
UNIV_INTERN
3377
 
void
3378
 
os_aio_simulated_put_read_threads_to_sleep(void)
3379
 
/*============================================*/
3380
 
{
3381
 
        os_aio_array_t* array;
3382
 
        ulint           g;
3383
 
 
3384
 
        os_aio_recommend_sleep_for_read_threads = TRUE;
3385
 
 
3386
 
        for (g = 0; g < os_aio_n_segments; g++) {
3387
 
                os_aio_get_array_and_local_segment(&array, g);
3388
 
 
3389
 
                if (array == os_aio_read_array) {
3390
 
 
3391
 
                        os_event_reset(os_aio_segment_wait_events[g]);
3392
 
                }
3393
 
        }
3394
 
}
3395
 
 
3396
 
/*******************************************************************//**
3397
 
Requests an asynchronous i/o operation.
3398
 
@return TRUE if request was queued successfully, FALSE if fail */
3399
 
UNIV_INTERN
3400
 
ibool
3401
 
os_aio(
3402
 
/*===*/
3403
 
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3404
 
        ulint           mode,   /*!< in: OS_AIO_NORMAL, ..., possibly ORed
3405
 
                                to OS_AIO_SIMULATED_WAKE_LATER: the
3406
 
                                last flag advises this function not to wake
3407
 
                                i/o-handler threads, but the caller will
3408
 
                                do the waking explicitly later, in this
3409
 
                                way the caller can post several requests in
3410
 
                                a batch; NOTE that the batch must not be
3411
 
                                so big that it exhausts the slots in aio
3412
 
                                arrays! NOTE that a simulated batch
3413
 
                                may introduce hidden chances of deadlocks,
3414
 
                                because i/os are not actually handled until
3415
 
                                all have been posted: use with great
3416
 
                                caution! */
3417
 
        const char*     name,   /*!< in: name of the file or path as a
3418
 
                                null-terminated string */
3419
 
        os_file_t       file,   /*!< in: handle to a file */
3420
 
        void*           buf,    /*!< in: buffer where to read or from which
3421
 
                                to write */
3422
 
        ulint           offset, /*!< in: least significant 32 bits of file
3423
 
                                offset where to read or write */
3424
 
        ulint           offset_high, /*!< in: most significant 32 bits of
3425
 
                                offset */
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
3430
 
                                OS_AIO_SYNC */
3431
 
        void*           message2)/*!< in: message for the aio handler
3432
 
                                (can be used to identify a completed
3433
 
                                aio operation); ignored if mode is
3434
 
                                OS_AIO_SYNC */
3435
 
{
3436
 
        os_aio_array_t* array;
3437
 
        os_aio_slot_t*  slot;
3438
 
#ifdef WIN_ASYNC_IO
3439
 
        ibool           retval;
3440
 
        BOOL            ret             = TRUE;
3441
 
        DWORD           len             = (DWORD) n;
3442
 
        struct fil_node_struct * dummy_mess1;
3443
 
        void*           dummy_mess2;
3444
 
        ulint           dummy_type;
3445
 
#endif
3446
 
        ulint           err             = 0;
3447
 
        ibool           retry;
3448
 
        ulint           wake_later;
3449
 
 
3450
 
        ut_ad(file);
3451
 
        ut_ad(buf);
3452
 
        ut_ad(n > 0);
3453
 
        ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
3454
 
        ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
3455
 
        ut_ad(os_aio_validate());
3456
 
 
3457
 
        wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
3458
 
        mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
3459
 
 
3460
 
        if (mode == OS_AIO_SYNC
3461
 
#ifdef WIN_ASYNC_IO
3462
 
            && !os_aio_use_native_aio
3463
 
#endif
3464
 
            ) {
3465
 
                /* This is actually an ordinary synchronous read or write:
3466
 
                no need to use an i/o-handler thread. NOTE that if we use
3467
 
                Windows async i/o, Windows does not allow us to use
3468
 
                ordinary synchronous os_file_read etc. on the same file,
3469
 
                therefore we have built a special mechanism for synchronous
3470
 
                wait in the Windows case. */
3471
 
 
3472
 
                if (type == OS_FILE_READ) {
3473
 
                        return(os_file_read(file, buf, offset,
3474
 
                                            offset_high, n));
3475
 
                }
3476
 
 
3477
 
                ut_a(type == OS_FILE_WRITE);
3478
 
 
3479
 
                return(os_file_write(name, file, buf, offset, offset_high, n));
3480
 
        }
3481
 
 
3482
 
try_again:
3483
 
        if (mode == OS_AIO_NORMAL) {
3484
 
                if (type == OS_FILE_READ) {
3485
 
                        array = os_aio_read_array;
3486
 
                } else {
3487
 
                        array = os_aio_write_array;
3488
 
                }
3489
 
        } else if (mode == OS_AIO_IBUF) {
3490
 
                ut_ad(type == OS_FILE_READ);
3491
 
                /* Reduce probability of deadlock bugs in connection with ibuf:
3492
 
                do not let the ibuf i/o handler sleep */
3493
 
 
3494
 
                wake_later = FALSE;
3495
 
 
3496
 
                array = os_aio_ibuf_array;
3497
 
        } else if (mode == OS_AIO_LOG) {
3498
 
 
3499
 
                array = os_aio_log_array;
3500
 
        } else if (mode == OS_AIO_SYNC) {
3501
 
                array = os_aio_sync_array;
3502
 
        } else {
3503
 
                array = NULL; /* Eliminate compiler warning */
3504
 
                ut_error;
3505
 
        }
3506
 
 
3507
 
        slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
3508
 
                                         name, buf, offset, offset_high, n);
3509
 
        if (type == OS_FILE_READ) {
3510
 
                if (os_aio_use_native_aio) {
3511
 
#ifdef WIN_ASYNC_IO
3512
 
                        os_n_file_reads++;
3513
 
                        os_bytes_read_since_printout += len;
3514
 
 
3515
 
                        ret = ReadFile(file, buf, (DWORD)n, &len,
3516
 
                                       &(slot->control));
3517
 
#endif
3518
 
                } else {
3519
 
                        if (!wake_later) {
3520
 
                                os_aio_simulated_wake_handler_thread(
3521
 
                                        os_aio_get_segment_no_from_slot(
3522
 
                                                array, slot));
3523
 
                        }
3524
 
                }
3525
 
        } else if (type == OS_FILE_WRITE) {
3526
 
                if (os_aio_use_native_aio) {
3527
 
#ifdef WIN_ASYNC_IO
3528
 
                        os_n_file_writes++;
3529
 
                        ret = WriteFile(file, buf, (DWORD)n, &len,
3530
 
                                        &(slot->control));
3531
 
#endif
3532
 
                } else {
3533
 
                        if (!wake_later) {
3534
 
                                os_aio_simulated_wake_handler_thread(
3535
 
                                        os_aio_get_segment_no_from_slot(
3536
 
                                                array, slot));
3537
 
                        }
3538
 
                }
3539
 
        } else {
3540
 
                ut_error;
3541
 
        }
3542
 
 
3543
 
#ifdef WIN_ASYNC_IO
3544
 
        if (os_aio_use_native_aio) {
3545
 
                if ((ret && len == n)
3546
 
                    || (!ret && GetLastError() == ERROR_IO_PENDING)) {
3547
 
                        /* aio was queued successfully! */
3548
 
 
3549
 
                        if (mode == OS_AIO_SYNC) {
3550
 
                                /* We want a synchronous i/o operation on a
3551
 
                                file where we also use async i/o: in Windows
3552
 
                                we must use the same wait mechanism as for
3553
 
                                async i/o */
3554
 
 
3555
 
                                retval = os_aio_windows_handle(ULINT_UNDEFINED,
3556
 
                                                               slot->pos,
3557
 
                                                               &dummy_mess1,
3558
 
                                                               &dummy_mess2,
3559
 
                                                               &dummy_type);
3560
 
 
3561
 
                                return(retval);
3562
 
                        }
3563
 
 
3564
 
                        return(TRUE);
3565
 
                }
3566
 
 
3567
 
                err = 1; /* Fall through the next if */
3568
 
        }
3569
 
#endif
3570
 
        if (err == 0) {
3571
 
                /* aio was queued successfully! */
3572
 
 
3573
 
                return(TRUE);
3574
 
        }
3575
 
 
3576
 
        os_aio_array_free_slot(array, slot);
3577
 
 
3578
 
        retry = os_file_handle_error(name,
3579
 
                                     type == OS_FILE_READ
3580
 
                                     ? "aio read" : "aio write");
3581
 
        if (retry) {
3582
 
 
3583
 
                goto try_again;
3584
 
        }
3585
 
 
3586
 
        return(FALSE);
3587
 
}
3588
 
 
3589
 
#ifdef WIN_ASYNC_IO
3590
 
/**********************************************************************//**
3591
 
This function is only used in Windows asynchronous i/o.
3592
 
Waits for an aio operation to complete. This function is used to wait the
3593
 
for completed requests. The aio array of pending requests is divided
3594
 
into segments. The thread specifies which segment or slot it wants to wait
3595
 
for. NOTE: this function will also take care of freeing the aio slot,
3596
 
therefore no other thread is allowed to do the freeing!
3597
 
@return TRUE if the aio operation succeeded */
3598
 
UNIV_INTERN
3599
 
ibool
3600
 
os_aio_windows_handle(
3601
 
/*==================*/
3602
 
        ulint   segment,        /*!< in: the number of the segment in the aio
3603
 
                                arrays to wait for; segment 0 is the ibuf
3604
 
                                i/o thread, segment 1 the log i/o thread,
3605
 
                                then follow the non-ibuf read threads, and as
3606
 
                                the last are the non-ibuf write threads; if
3607
 
                                this is ULINT_UNDEFINED, then it means that
3608
 
                                sync aio is used, and this parameter is
3609
 
                                ignored */
3610
 
        ulint   pos,            /*!< this parameter is used only in sync aio:
3611
 
                                wait for the aio slot at this position */
3612
 
        fil_node_t**message1,   /*!< out: the messages passed with the aio
3613
 
                                request; note that also in the case where
3614
 
                                the aio operation failed, these output
3615
 
                                parameters are valid and can be used to
3616
 
                                restart the operation, for example */
3617
 
        void**  message2,
3618
 
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
3619
 
{
3620
 
        ulint           orig_seg        = segment;
3621
 
        os_aio_array_t* array;
3622
 
        os_aio_slot_t*  slot;
3623
 
        ulint           n;
3624
 
        ulint           i;
3625
 
        ibool           ret_val;
3626
 
        BOOL            ret;
3627
 
        DWORD           len;
3628
 
 
3629
 
        if (segment == ULINT_UNDEFINED) {
3630
 
                array = os_aio_sync_array;
3631
 
                segment = 0;
3632
 
        } else {
3633
 
                segment = os_aio_get_array_and_local_segment(&array, segment);
3634
 
        }
3635
 
 
3636
 
        /* NOTE! We only access constant fields in os_aio_array. Therefore
3637
 
        we do not have to acquire the protecting mutex yet */
3638
 
 
3639
 
        ut_ad(os_aio_validate());
3640
 
        ut_ad(segment < array->n_segments);
3641
 
 
3642
 
        n = array->n_slots / array->n_segments;
3643
 
 
3644
 
        if (array == os_aio_sync_array) {
3645
 
                os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
3646
 
                i = pos;
3647
 
        } else {
3648
 
                srv_set_io_thread_op_info(orig_seg, "wait Windows aio");
3649
 
                i = os_event_wait_multiple(n,
3650
 
                                           (array->native_events)
3651
 
                                           + segment * n);
3652
 
        }
3653
 
 
3654
 
        os_mutex_enter(array->mutex);
3655
 
 
3656
 
        slot = os_aio_array_get_nth_slot(array, i + segment * n);
3657
 
 
3658
 
        ut_a(slot->reserved);
3659
 
 
3660
 
        if (orig_seg != ULINT_UNDEFINED) {
3661
 
                srv_set_io_thread_op_info(orig_seg,
3662
 
                                          "get windows aio return value");
3663
 
        }
3664
 
 
3665
 
        ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
3666
 
 
3667
 
        *message1 = slot->message1;
3668
 
        *message2 = slot->message2;
3669
 
 
3670
 
        *type = slot->type;
3671
 
 
3672
 
        if (ret && len == slot->len) {
3673
 
                ret_val = TRUE;
3674
 
 
3675
 
#ifdef UNIV_DO_FLUSH
3676
 
                if (slot->type == OS_FILE_WRITE
3677
 
                    && !os_do_not_call_flush_at_each_write) {
3678
 
                        ut_a(TRUE == os_file_flush(slot->file));
3679
 
                }
3680
 
#endif /* UNIV_DO_FLUSH */
3681
 
        } else {
3682
 
                os_file_handle_error(slot->name, "Windows aio");
3683
 
 
3684
 
                ret_val = FALSE;
3685
 
        }
3686
 
 
3687
 
        os_mutex_exit(array->mutex);
3688
 
 
3689
 
        os_aio_array_free_slot(array, slot);
3690
 
 
3691
 
        return(ret_val);
3692
 
}
3693
 
#endif
3694
 
 
3695
 
/**********************************************************************//**
3696
 
Does simulated aio. This function should be called by an i/o-handler
3697
 
thread.
3698
 
@return TRUE if the aio operation succeeded */
3699
 
UNIV_INTERN
3700
 
ibool
3701
 
os_aio_simulated_handle(
3702
 
/*====================*/
3703
 
        ulint   global_segment, /*!< in: the number of the segment in the aio
3704
 
                                arrays to wait for; segment 0 is the ibuf
3705
 
                                i/o thread, segment 1 the log i/o thread,
3706
 
                                then follow the non-ibuf read threads, and as
3707
 
                                the last are the non-ibuf write threads */
3708
 
        fil_node_t**message1,   /*!< out: the messages passed with the aio
3709
 
                                request; note that also in the case where
3710
 
                                the aio operation failed, these output
3711
 
                                parameters are valid and can be used to
3712
 
                                restart the operation, for example */
3713
 
        void**  message2,
3714
 
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
3715
 
{
3716
 
        os_aio_array_t* array;
3717
 
        ulint           segment;
3718
 
        os_aio_slot_t*  slot;
3719
 
        os_aio_slot_t*  slot2;
3720
 
        os_aio_slot_t*  consecutive_ios[OS_AIO_MERGE_N_CONSECUTIVE];
3721
 
        ulint           n_consecutive;
3722
 
        ulint           total_len;
3723
 
        ulint           offs;
3724
 
        ulint           lowest_offset;
3725
 
        ulint           biggest_age;
3726
 
        ulint           age;
3727
 
        byte*           combined_buf;
3728
 
        byte*           combined_buf2;
3729
 
        ibool           ret;
3730
 
        ulint           n;
3731
 
        ulint           i;
3732
 
 
3733
 
        memset(consecutive_ios, 0, sizeof(os_aio_slot_t*) * OS_AIO_MERGE_N_CONSECUTIVE);
3734
 
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
3735
 
 
3736
 
restart:
3737
 
        /* NOTE! We only access constant fields in os_aio_array. Therefore
3738
 
        we do not have to acquire the protecting mutex yet */
3739
 
 
3740
 
        srv_set_io_thread_op_info(global_segment,
3741
 
                                  "looking for i/o requests (a)");
3742
 
        ut_ad(os_aio_validate());
3743
 
        ut_ad(segment < array->n_segments);
3744
 
 
3745
 
        n = array->n_slots / array->n_segments;
3746
 
 
3747
 
        /* Look through n slots after the segment * n'th slot */
3748
 
 
3749
 
        if (array == os_aio_read_array
3750
 
            && os_aio_recommend_sleep_for_read_threads) {
3751
 
 
3752
 
                /* Give other threads chance to add several i/os to the array
3753
 
                at once. */
3754
 
 
3755
 
                goto recommended_sleep;
3756
 
        }
3757
 
 
3758
 
        os_mutex_enter(array->mutex);
3759
 
 
3760
 
        srv_set_io_thread_op_info(global_segment,
3761
 
                                  "looking for i/o requests (b)");
3762
 
 
3763
 
        /* Check if there is a slot for which the i/o has already been
3764
 
        done */
3765
 
 
3766
 
        for (i = 0; i < n; i++) {
3767
 
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
3768
 
 
3769
 
                if (slot->reserved && slot->io_already_done) {
3770
 
 
3771
 
                        if (os_aio_print_debug) {
3772
 
                                fprintf(stderr,
3773
 
                                        "InnoDB: i/o for slot %lu"
3774
 
                                        " already done, returning\n",
3775
 
                                        (ulong) i);
3776
 
                        }
3777
 
 
3778
 
                        ret = TRUE;
3779
 
 
3780
 
                        goto slot_io_done;
3781
 
                }
3782
 
        }
3783
 
 
3784
 
        n_consecutive = 0;
3785
 
 
3786
 
        /* If there are at least 2 seconds old requests, then pick the oldest
3787
 
        one to prevent starvation. If several requests have the same age,
3788
 
        then pick the one at the lowest offset. */
3789
 
 
3790
 
        biggest_age = 0;
3791
 
        lowest_offset = ULINT_MAX;
3792
 
 
3793
 
        for (i = 0; i < n; i++) {
3794
 
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
3795
 
 
3796
 
                if (slot->reserved) {
3797
 
                        age = (ulint)difftime(time(NULL),
3798
 
                                              slot->reservation_time);
3799
 
 
3800
 
                        if ((age >= 2 && age > biggest_age)
3801
 
                            || (age >= 2 && age == biggest_age
3802
 
                                && slot->offset < lowest_offset)) {
3803
 
 
3804
 
                                /* Found an i/o request */
3805
 
                                consecutive_ios[0] = slot;
3806
 
 
3807
 
                                n_consecutive = 1;
3808
 
 
3809
 
                                biggest_age = age;
3810
 
                                lowest_offset = slot->offset;
3811
 
                        }
3812
 
                }
3813
 
        }
3814
 
 
3815
 
        if (n_consecutive == 0) {
3816
 
                /* There were no old requests. Look for an i/o request at the
3817
 
                lowest offset in the array (we ignore the high 32 bits of the
3818
 
                offset in these heuristics) */
3819
 
 
3820
 
                lowest_offset = ULINT_MAX;
3821
 
 
3822
 
                for (i = 0; i < n; i++) {
3823
 
                        slot = os_aio_array_get_nth_slot(array,
3824
 
                                                         i + segment * n);
3825
 
 
3826
 
                        if (slot->reserved && slot->offset < lowest_offset) {
3827
 
 
3828
 
                                /* Found an i/o request */
3829
 
                                consecutive_ios[0] = slot;
3830
 
 
3831
 
                                n_consecutive = 1;
3832
 
 
3833
 
                                lowest_offset = slot->offset;
3834
 
                        }
3835
 
                }
3836
 
        }
3837
 
 
3838
 
        if (n_consecutive == 0) {
3839
 
 
3840
 
                /* No i/o requested at the moment */
3841
 
 
3842
 
                goto wait_for_io;
3843
 
        }
3844
 
 
3845
 
        slot = consecutive_ios[0];
3846
 
 
3847
 
        /* Check if there are several consecutive blocks to read or write */
3848
 
 
3849
 
consecutive_loop:
3850
 
        for (i = 0; i < n; i++) {
3851
 
                slot2 = os_aio_array_get_nth_slot(array, i + segment * n);
3852
 
 
3853
 
                if (slot2->reserved && slot2 != slot
3854
 
                    && slot2->offset == slot->offset + slot->len
3855
 
                    /* check that sum does not wrap over */
3856
 
                    && slot->offset + slot->len > slot->offset
3857
 
                    && slot2->offset_high == slot->offset_high
3858
 
                    && slot2->type == slot->type
3859
 
                    && slot2->file == slot->file) {
3860
 
 
3861
 
                        /* Found a consecutive i/o request */
3862
 
 
3863
 
                        consecutive_ios[n_consecutive] = slot2;
3864
 
                        n_consecutive++;
3865
 
 
3866
 
                        slot = slot2;
3867
 
 
3868
 
                        if (n_consecutive < OS_AIO_MERGE_N_CONSECUTIVE) {
3869
 
 
3870
 
                                goto consecutive_loop;
3871
 
                        } else {
3872
 
                                break;
3873
 
                        }
3874
 
                }
3875
 
        }
3876
 
 
3877
 
        srv_set_io_thread_op_info(global_segment, "consecutive i/o requests");
3878
 
 
3879
 
        /* We have now collected n_consecutive i/o requests in the array;
3880
 
        allocate a single buffer which can hold all data, and perform the
3881
 
        i/o */
3882
 
 
3883
 
        total_len = 0;
3884
 
        slot = consecutive_ios[0];
3885
 
 
3886
 
        for (i = 0; i < n_consecutive; i++) {
3887
 
                total_len += consecutive_ios[i]->len;
3888
 
        }
3889
 
 
3890
 
        if (n_consecutive == 1) {
3891
 
                /* We can use the buffer of the i/o request */
3892
 
                combined_buf = slot->buf;
3893
 
                combined_buf2 = NULL;
3894
 
        } else {
3895
 
                combined_buf2 = ut_malloc(total_len + UNIV_PAGE_SIZE);
3896
 
 
3897
 
                ut_a(combined_buf2);
3898
 
 
3899
 
                combined_buf = ut_align(combined_buf2, UNIV_PAGE_SIZE);
3900
 
        }
3901
 
 
3902
 
        /* We release the array mutex for the time of the i/o: NOTE that
3903
 
        this assumes that there is just one i/o-handler thread serving
3904
 
        a single segment of slots! */
3905
 
 
3906
 
        os_mutex_exit(array->mutex);
3907
 
 
3908
 
        if (slot->type == OS_FILE_WRITE && n_consecutive > 1) {
3909
 
                /* Copy the buffers to the combined buffer */
3910
 
                offs = 0;
3911
 
 
3912
 
                for (i = 0; i < n_consecutive; i++) {
3913
 
 
3914
 
                        ut_memcpy(combined_buf + offs, consecutive_ios[i]->buf,
3915
 
                                  consecutive_ios[i]->len);
3916
 
                        offs += consecutive_ios[i]->len;
3917
 
                }
3918
 
        }
3919
 
 
3920
 
        srv_set_io_thread_op_info(global_segment, "doing file i/o");
3921
 
 
3922
 
        if (os_aio_print_debug) {
3923
 
                fprintf(stderr,
3924
 
                        "InnoDB: doing i/o of type %lu at offset %lu %lu,"
3925
 
                        " length %lu\n",
3926
 
                        (ulong) slot->type, (ulong) slot->offset_high,
3927
 
                        (ulong) slot->offset, (ulong) total_len);
3928
 
        }
3929
 
 
3930
 
        /* Do the i/o with ordinary, synchronous i/o functions: */
3931
 
        if (slot->type == OS_FILE_WRITE) {
3932
 
                ret = os_file_write(slot->name, slot->file, combined_buf,
3933
 
                                    slot->offset, slot->offset_high,
3934
 
                                    total_len);
3935
 
        } else {
3936
 
                ret = os_file_read(slot->file, combined_buf,
3937
 
                                   slot->offset, slot->offset_high, total_len);
3938
 
        }
3939
 
 
3940
 
        ut_a(ret);
3941
 
        srv_set_io_thread_op_info(global_segment, "file i/o done");
3942
 
 
3943
 
#if 0
3944
 
        fprintf(stderr,
3945
 
                "aio: %lu consecutive %lu:th segment, first offs %lu blocks\n",
3946
 
                n_consecutive, global_segment, slot->offset / UNIV_PAGE_SIZE);
3947
 
#endif
3948
 
 
3949
 
        if (slot->type == OS_FILE_READ && n_consecutive > 1) {
3950
 
                /* Copy the combined buffer to individual buffers */
3951
 
                offs = 0;
3952
 
 
3953
 
                for (i = 0; i < n_consecutive; i++) {
3954
 
 
3955
 
                        ut_memcpy(consecutive_ios[i]->buf, combined_buf + offs,
3956
 
                                  consecutive_ios[i]->len);
3957
 
                        offs += consecutive_ios[i]->len;
3958
 
                }
3959
 
        }
3960
 
 
3961
 
        if (combined_buf2) {
3962
 
                ut_free(combined_buf2);
3963
 
        }
3964
 
 
3965
 
        os_mutex_enter(array->mutex);
3966
 
 
3967
 
        /* Mark the i/os done in slots */
3968
 
 
3969
 
        for (i = 0; i < n_consecutive; i++) {
3970
 
                consecutive_ios[i]->io_already_done = TRUE;
3971
 
        }
3972
 
 
3973
 
        /* We return the messages for the first slot now, and if there were
3974
 
        several slots, the messages will be returned with subsequent calls
3975
 
        of this function */
3976
 
 
3977
 
slot_io_done:
3978
 
 
3979
 
        ut_a(slot->reserved);
3980
 
 
3981
 
        *message1 = slot->message1;
3982
 
        *message2 = slot->message2;
3983
 
 
3984
 
        *type = slot->type;
3985
 
 
3986
 
        os_mutex_exit(array->mutex);
3987
 
 
3988
 
        os_aio_array_free_slot(array, slot);
3989
 
 
3990
 
        return(ret);
3991
 
 
3992
 
wait_for_io:
3993
 
        srv_set_io_thread_op_info(global_segment, "resetting wait event");
3994
 
 
3995
 
        /* We wait here until there again can be i/os in the segment
3996
 
        of this thread */
3997
 
 
3998
 
        os_event_reset(os_aio_segment_wait_events[global_segment]);
3999
 
 
4000
 
        os_mutex_exit(array->mutex);
4001
 
 
4002
 
recommended_sleep:
4003
 
        srv_set_io_thread_op_info(global_segment, "waiting for i/o request");
4004
 
 
4005
 
        os_event_wait(os_aio_segment_wait_events[global_segment]);
4006
 
 
4007
 
        if (os_aio_print_debug) {
4008
 
                fprintf(stderr,
4009
 
                        "InnoDB: i/o handler thread for i/o"
4010
 
                        " segment %lu wakes up\n",
4011
 
                        (ulong) global_segment);
4012
 
        }
4013
 
 
4014
 
        goto restart;
4015
 
}
4016
 
 
4017
 
/**********************************************************************//**
4018
 
Validates the consistency of an aio array.
4019
 
@return TRUE if ok */
4020
 
static
4021
 
ibool
4022
 
os_aio_array_validate(
4023
 
/*==================*/
4024
 
        os_aio_array_t* array)  /*!< in: aio wait array */
4025
 
{
4026
 
        os_aio_slot_t*  slot;
4027
 
        ulint           n_reserved      = 0;
4028
 
        ulint           i;
4029
 
 
4030
 
        ut_a(array);
4031
 
 
4032
 
        os_mutex_enter(array->mutex);
4033
 
 
4034
 
        ut_a(array->n_slots > 0);
4035
 
        ut_a(array->n_segments > 0);
4036
 
 
4037
 
        for (i = 0; i < array->n_slots; i++) {
4038
 
                slot = os_aio_array_get_nth_slot(array, i);
4039
 
 
4040
 
                if (slot->reserved) {
4041
 
                        n_reserved++;
4042
 
                        ut_a(slot->len > 0);
4043
 
                }
4044
 
        }
4045
 
 
4046
 
        ut_a(array->n_reserved == n_reserved);
4047
 
 
4048
 
        os_mutex_exit(array->mutex);
4049
 
 
4050
 
        return(TRUE);
4051
 
}
4052
 
 
4053
 
/**********************************************************************//**
4054
 
Validates the consistency the aio system.
4055
 
@return TRUE if ok */
4056
 
UNIV_INTERN
4057
 
ibool
4058
 
os_aio_validate(void)
4059
 
/*=================*/
4060
 
{
4061
 
        os_aio_array_validate(os_aio_read_array);
4062
 
        os_aio_array_validate(os_aio_write_array);
4063
 
        os_aio_array_validate(os_aio_ibuf_array);
4064
 
        os_aio_array_validate(os_aio_log_array);
4065
 
        os_aio_array_validate(os_aio_sync_array);
4066
 
 
4067
 
        return(TRUE);
4068
 
}
4069
 
 
4070
 
/**********************************************************************//**
4071
 
Prints info of the aio arrays. */
4072
 
UNIV_INTERN
4073
 
void
4074
 
os_aio_print(
4075
 
/*=========*/
4076
 
        FILE*   file)   /*!< in: file where to print */
4077
 
{
4078
 
        os_aio_array_t* array;
4079
 
        os_aio_slot_t*  slot;
4080
 
        ulint           n_reserved;
4081
 
        time_t          current_time;
4082
 
        double          time_elapsed;
4083
 
        double          avg_bytes_read;
4084
 
        ulint           i;
4085
 
 
4086
 
        for (i = 0; i < srv_n_file_io_threads; i++) {
4087
 
                fprintf(file, "I/O thread %lu state: %s (%s)", (ulong) i,
4088
 
                        srv_io_thread_op_info[i],
4089
 
                        srv_io_thread_function[i]);
4090
 
 
4091
 
#ifndef __WIN__
4092
 
                if (os_aio_segment_wait_events[i]->is_set) {
4093
 
                        fprintf(file, " ev set");
4094
 
                }
4095
 
#endif
4096
 
 
4097
 
                fprintf(file, "\n");
4098
 
        }
4099
 
 
4100
 
        fputs("Pending normal aio reads:", file);
4101
 
 
4102
 
        array = os_aio_read_array;
4103
 
loop:
4104
 
        ut_a(array);
4105
 
 
4106
 
        os_mutex_enter(array->mutex);
4107
 
 
4108
 
        ut_a(array->n_slots > 0);
4109
 
        ut_a(array->n_segments > 0);
4110
 
 
4111
 
        n_reserved = 0;
4112
 
 
4113
 
        for (i = 0; i < array->n_slots; i++) {
4114
 
                slot = os_aio_array_get_nth_slot(array, i);
4115
 
 
4116
 
                if (slot->reserved) {
4117
 
                        n_reserved++;
4118
 
#if 0
4119
 
                        fprintf(stderr, "Reserved slot, messages %p %p\n",
4120
 
                                (void*) slot->message1,
4121
 
                                (void*) slot->message2);
4122
 
#endif
4123
 
                        ut_a(slot->len > 0);
4124
 
                }
4125
 
        }
4126
 
 
4127
 
        ut_a(array->n_reserved == n_reserved);
4128
 
 
4129
 
        fprintf(file, " %lu", (ulong) n_reserved);
4130
 
 
4131
 
        os_mutex_exit(array->mutex);
4132
 
 
4133
 
        if (array == os_aio_read_array) {
4134
 
                fputs(", aio writes:", file);
4135
 
 
4136
 
                array = os_aio_write_array;
4137
 
 
4138
 
                goto loop;
4139
 
        }
4140
 
 
4141
 
        if (array == os_aio_write_array) {
4142
 
                fputs(",\n ibuf aio reads:", file);
4143
 
                array = os_aio_ibuf_array;
4144
 
 
4145
 
                goto loop;
4146
 
        }
4147
 
 
4148
 
        if (array == os_aio_ibuf_array) {
4149
 
                fputs(", log i/o's:", file);
4150
 
                array = os_aio_log_array;
4151
 
 
4152
 
                goto loop;
4153
 
        }
4154
 
 
4155
 
        if (array == os_aio_log_array) {
4156
 
                fputs(", sync i/o's:", file);
4157
 
                array = os_aio_sync_array;
4158
 
 
4159
 
                goto loop;
4160
 
        }
4161
 
 
4162
 
        putc('\n', file);
4163
 
        current_time = time(NULL);
4164
 
        time_elapsed = 0.001 + difftime(current_time, os_last_printout);
4165
 
 
4166
 
        fprintf(file,
4167
 
                "Pending flushes (fsync) log: %lu; buffer pool: %lu\n"
4168
 
                "%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n",
4169
 
                (ulong) fil_n_pending_log_flushes,
4170
 
                (ulong) fil_n_pending_tablespace_flushes,
4171
 
                (ulong) os_n_file_reads, (ulong) os_n_file_writes,
4172
 
                (ulong) os_n_fsyncs);
4173
 
 
4174
 
        if (os_file_n_pending_preads != 0 || os_file_n_pending_pwrites != 0) {
4175
 
                fprintf(file,
4176
 
                        "%lu pending preads, %lu pending pwrites\n",
4177
 
                        (ulong) os_file_n_pending_preads,
4178
 
                        (ulong) os_file_n_pending_pwrites);
4179
 
        }
4180
 
 
4181
 
        if (os_n_file_reads == os_n_file_reads_old) {
4182
 
                avg_bytes_read = 0.0;
4183
 
        } else {
4184
 
                avg_bytes_read = (double) os_bytes_read_since_printout
4185
 
                        / (os_n_file_reads - os_n_file_reads_old);
4186
 
        }
4187
 
 
4188
 
        fprintf(file,
4189
 
                "%.2f reads/s, %lu avg bytes/read,"
4190
 
                " %.2f writes/s, %.2f fsyncs/s\n",
4191
 
                (os_n_file_reads - os_n_file_reads_old)
4192
 
                / time_elapsed,
4193
 
                (ulong)avg_bytes_read,
4194
 
                (os_n_file_writes - os_n_file_writes_old)
4195
 
                / time_elapsed,
4196
 
                (os_n_fsyncs - os_n_fsyncs_old)
4197
 
                / time_elapsed);
4198
 
 
4199
 
        os_n_file_reads_old = os_n_file_reads;
4200
 
        os_n_file_writes_old = os_n_file_writes;
4201
 
        os_n_fsyncs_old = os_n_fsyncs;
4202
 
        os_bytes_read_since_printout = 0;
4203
 
 
4204
 
        os_last_printout = current_time;
4205
 
}
4206
 
 
4207
 
/**********************************************************************//**
4208
 
Refreshes the statistics used to print per-second averages. */
4209
 
UNIV_INTERN
4210
 
void
4211
 
os_aio_refresh_stats(void)
4212
 
/*======================*/
4213
 
{
4214
 
        os_n_file_reads_old = os_n_file_reads;
4215
 
        os_n_file_writes_old = os_n_file_writes;
4216
 
        os_n_fsyncs_old = os_n_fsyncs;
4217
 
        os_bytes_read_since_printout = 0;
4218
 
 
4219
 
        os_last_printout = time(NULL);
4220
 
}
4221
 
 
4222
 
#ifdef UNIV_DEBUG
4223
 
/**********************************************************************//**
4224
 
Checks that all slots in the system have been freed, that is, there are
4225
 
no pending io operations.
4226
 
@return TRUE if all free */
4227
 
UNIV_INTERN
4228
 
ibool
4229
 
os_aio_all_slots_free(void)
4230
 
/*=======================*/
4231
 
{
4232
 
        os_aio_array_t* array;
4233
 
        ulint           n_res   = 0;
4234
 
 
4235
 
        array = os_aio_read_array;
4236
 
 
4237
 
        os_mutex_enter(array->mutex);
4238
 
 
4239
 
        n_res += array->n_reserved;
4240
 
 
4241
 
        os_mutex_exit(array->mutex);
4242
 
 
4243
 
        array = os_aio_write_array;
4244
 
 
4245
 
        os_mutex_enter(array->mutex);
4246
 
 
4247
 
        n_res += array->n_reserved;
4248
 
 
4249
 
        os_mutex_exit(array->mutex);
4250
 
 
4251
 
        array = os_aio_ibuf_array;
4252
 
 
4253
 
        os_mutex_enter(array->mutex);
4254
 
 
4255
 
        n_res += array->n_reserved;
4256
 
 
4257
 
        os_mutex_exit(array->mutex);
4258
 
 
4259
 
        array = os_aio_log_array;
4260
 
 
4261
 
        os_mutex_enter(array->mutex);
4262
 
 
4263
 
        n_res += array->n_reserved;
4264
 
 
4265
 
        os_mutex_exit(array->mutex);
4266
 
 
4267
 
        array = os_aio_sync_array;
4268
 
 
4269
 
        os_mutex_enter(array->mutex);
4270
 
 
4271
 
        n_res += array->n_reserved;
4272
 
 
4273
 
        os_mutex_exit(array->mutex);
4274
 
 
4275
 
        if (n_res == 0) {
4276
 
 
4277
 
                return(TRUE);
4278
 
        }
4279
 
 
4280
 
        return(FALSE);
4281
 
}
4282
 
#endif /* UNIV_DEBUG */
4283
 
 
4284
 
#endif /* !UNIV_HOTBACKUP */