~ubuntu-branches/ubuntu/saucy/drizzle/saucy-proposed

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

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 */