~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-12-08 22:35:56 UTC
  • mfrom: (1819.9.158 update-innobase)
  • Revision ID: brian@tangent.org-20101208223556-37mi4omqg7lkjzf3
Merge in Stewart's changes, 1.3 changes.

Show diffs side-by-side

added added

removed removed

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