~mysql/mysql-server/mysql-6.0

« back to all changes in this revision

Viewing changes to innobase/os/os0file.c

  • Committer: monty at mysql
  • Date: 2001-02-17 12:19:19 UTC
  • mto: (554.1.1)
  • mto: This revision was merged to the branch mainline in revision 556.
  • Revision ID: sp1r-monty@donna.mysql.com-20010217121919-07904
Added Innobase to source distribution

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 "ut0mem.h"
 
12
 
 
13
 
 
14
#ifdef POSIX_ASYNC_IO
 
15
/* We assume in this case that the OS has standard Posix aio (at least SunOS
 
16
2.6, HP-UX 11i and AIX 4.3 have) */
 
17
 
 
18
#undef __USE_FILE_OFFSET64
 
19
 
 
20
#include <aio.h>
 
21
#endif
 
22
 
 
23
/* We use these mutexes to protect lseek + file i/o operation, if the
 
24
OS does not provide an atomic pread or pwrite, or similar */
 
25
#define OS_FILE_N_SEEK_MUTEXES  16
 
26
os_mutex_t      os_file_seek_mutexes[OS_FILE_N_SEEK_MUTEXES];
 
27
 
 
28
/* In simulated aio, merge at most this many consecutive i/os */
 
29
#define OS_AIO_MERGE_N_CONSECUTIVE      32
 
30
 
 
31
/* If this flag is TRUE, then we will use the native aio of the
 
32
OS (provided we compiled Innobase with it in), otherwise we will
 
33
use simulated aio we build below with threads */
 
34
 
 
35
ibool   os_aio_use_native_aio   = FALSE;
 
36
 
 
37
/* The aio array slot structure */
 
38
typedef struct os_aio_slot_struct       os_aio_slot_t;
 
39
 
 
40
struct os_aio_slot_struct{
 
41
        ibool           is_read;        /* TRUE if a read operation */
 
42
        ulint           pos;            /* index of the slot in the aio
 
43
                                        array */
 
44
        ibool           reserved;       /* TRUE if this slot is reserved */
 
45
        ulint           len;            /* length of the block to read or
 
46
                                        write */
 
47
        byte*           buf;            /* buffer used in i/o */
 
48
        ulint           type;           /* OS_FILE_READ or OS_FILE_WRITE */
 
49
        ulint           offset;         /* 32 low bits of file offset in
 
50
                                        bytes */
 
51
        ulint           offset_high;    /* 32 high bits of file offset */
 
52
        os_file_t       file;           /* file where to read or write */
 
53
        char*           name;           /* file name or path */
 
54
        ibool           io_already_done;/* used only in simulated aio:
 
55
                                        TRUE if the physical i/o already
 
56
                                        made and only the slot message
 
57
                                        needs to be passed to the caller
 
58
                                        of os_aio_simulated_handle */
 
59
        void*           message1;       /* message which is given by the */
 
60
        void*           message2;       /* the requester of an aio operation
 
61
                                        and which can be used to identify
 
62
                                        which pending aio operation was
 
63
                                        completed */
 
64
#ifdef WIN_ASYNC_IO
 
65
        OVERLAPPED      control;        /* Windows control block for the
 
66
                                        aio request */
 
67
#elif defined(POSIX_ASYNC_IO)
 
68
        struct aiocb    control;        /* Posix control block for aio
 
69
                                        request */
 
70
#endif
 
71
};
 
72
 
 
73
/* The aio array structure */
 
74
typedef struct os_aio_array_struct      os_aio_array_t;
 
75
 
 
76
struct os_aio_array_struct{
 
77
        os_mutex_t      mutex;    /* the mutex protecting the aio array */
 
78
        os_event_t      not_full; /* The event which is set to signaled
 
79
                                  state when there is space in the aio
 
80
                                  outside the ibuf segment */
 
81
        ulint           n_slots;  /* Total number of slots in the aio array.
 
82
                                  This must be divisible by n_threads. */
 
83
        ulint           n_segments;/* Number of segments in the aio array of
 
84
                                  pending aio requests. A thread can wait
 
85
                                  separately for any one of the segments. */
 
86
        ulint           n_reserved;/* Number of reserved slots in the
 
87
                                  aio array outside the ibuf segment */
 
88
        os_aio_slot_t*  slots;    /* Pointer to the slots in the array */
 
89
        os_event_t*     events;   /* Pointer to an array of event handles
 
90
                                  where we copied the handles from slots,
 
91
                                  in the same order. This can be used in
 
92
                                  WaitForMultipleObjects; used only in
 
93
                                  Windows */
 
94
};
 
95
 
 
96
/* Array of events used in simulated aio */
 
97
os_event_t*     os_aio_segment_wait_events      = NULL;
 
98
 
 
99
/* The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These
 
100
are NULL when the module has not yet been initialized. */
 
101
os_aio_array_t* os_aio_read_array       = NULL;
 
102
os_aio_array_t* os_aio_write_array      = NULL;
 
103
os_aio_array_t* os_aio_ibuf_array       = NULL;
 
104
os_aio_array_t* os_aio_log_array        = NULL;
 
105
os_aio_array_t* os_aio_sync_array       = NULL;
 
106
 
 
107
ulint   os_aio_n_segments       = ULINT_UNDEFINED;
 
108
 
 
109
/***************************************************************************
 
110
Retrieves the last error number if an error occurs in a file io function.
 
111
The number should be retrieved before any other OS calls (because they may
 
112
overwrite the error number). If the number is not known to this program,
 
113
the OS error number + 100 is returned. */
 
114
 
 
115
ulint
 
116
os_file_get_last_error(void)
 
117
/*========================*/
 
118
                /* out: error number, or OS error number + 100 */
 
119
{
 
120
        ulint   err;
 
121
 
 
122
#ifdef __WIN__
 
123
 
 
124
        err = (ulint) GetLastError();
 
125
 
 
126
        if (err == ERROR_FILE_NOT_FOUND) {
 
127
                return(OS_FILE_NOT_FOUND);
 
128
        } else if (err == ERROR_DISK_FULL) {
 
129
                return(OS_FILE_DISK_FULL);
 
130
        } else if (err == ERROR_FILE_EXISTS) {
 
131
                return(OS_FILE_ALREADY_EXISTS);
 
132
        } else {
 
133
                return(100 + err);
 
134
        }
 
135
#else
 
136
        err = (ulint) errno;
 
137
 
 
138
        if (err == ENOSPC ) {
 
139
                return(OS_FILE_DISK_FULL);
 
140
#ifdef POSIX_ASYNC_IO
 
141
        } else if (err == EAGAIN) {
 
142
                return(OS_FILE_AIO_RESOURCES_RESERVED);
 
143
#endif
 
144
        } else if (err == ENOENT) {
 
145
                return(OS_FILE_NOT_FOUND);
 
146
        } else if (err == EEXIST) {
 
147
                return(OS_FILE_ALREADY_EXISTS);
 
148
        } else {
 
149
                return(100 + err);
 
150
        }
 
151
#endif
 
152
}
 
153
 
 
154
/********************************************************************
 
155
Does error handling when a file operation fails. If we have run out
 
156
of disk space, then the user can clean the disk. If we do not find
 
157
a specified file, then the user can copy it to disk. */
 
158
static
 
159
ibool
 
160
os_file_handle_error(
 
161
/*=================*/
 
162
                                /* out: TRUE if we should retry the operation */
 
163
        os_file_t       file,   /* in: file pointer */
 
164
        char*           name)   /* in: name of a file or NULL */
 
165
{
 
166
        int     input_char;
 
167
        ulint   err;
 
168
 
 
169
        err = os_file_get_last_error();
 
170
        
 
171
        if (err == OS_FILE_DISK_FULL) {
 
172
ask_again:
 
173
                printf("\n");
 
174
                if (name) {
 
175
                        printf(
 
176
                        "Innobase encountered a problem with file %s.\n",
 
177
                                                                        name);
 
178
                }
 
179
                printf("Disk is full. Try to clean the disk to free space\n");
 
180
                printf("before answering the following: How to continue?\n");
 
181
                printf("(Y == freed some space: try again)\n");
 
182
                printf("(N == crash the database: will restart it)?\n");
 
183
ask_with_no_question:
 
184
                input_char = getchar();
 
185
 
 
186
                if (input_char == (int) 'N') {
 
187
                        ut_error;
 
188
                
 
189
                        return(FALSE);
 
190
                } else if (input_char == (int) 'Y') {
 
191
 
 
192
                        return(TRUE);
 
193
                } else if (input_char == (int) '\n') {
 
194
 
 
195
                        goto ask_with_no_question;
 
196
                } else {
 
197
                        goto ask_again;
 
198
                }
 
199
        } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
 
200
 
 
201
                return(TRUE);
 
202
        } else {
 
203
                ut_error;
 
204
        }
 
205
 
 
206
        return(FALSE);  
 
207
}
 
208
 
 
209
/********************************************************************
 
210
Opens an existing file or creates a new. */
 
211
 
 
212
os_file_t
 
213
os_file_create(
 
214
/*===========*/
 
215
                        /* out, own: handle to the file, not defined if error,
 
216
                        error number can be retrieved with os_get_last_error */
 
217
        char*   name,   /* in: name of the file or path as a null-terminated
 
218
                        string */
 
219
        ulint   create_mode, /* in: OS_FILE_OPEN if an existing file is opened
 
220
                        (if does not exist, error), or OS_FILE_CREATE if a new
 
221
                        file is created (if exists, error), OS_FILE_OVERWRITE
 
222
                        if a new is created or an old overwritten */
 
223
        ulint   purpose,/* in: OS_FILE_AIO, if asynchronous, non-buffered i/o
 
224
                        is desired, OS_FILE_NORMAL, if any normal file */
 
225
        ibool*  success)/* out: TRUE if succeed, FALSE if error */
 
226
{
 
227
#ifdef __WIN__
 
228
        os_file_t       file;
 
229
        DWORD           create_flag;
 
230
        DWORD           attributes;
 
231
        ibool           retry;
 
232
        
 
233
try_again:      
 
234
        ut_a(name);
 
235
 
 
236
        if (create_mode == OS_FILE_OPEN) {
 
237
                create_flag = OPEN_EXISTING;
 
238
        } else if (create_mode == OS_FILE_CREATE) {
 
239
                create_flag = CREATE_NEW;
 
240
        } else if (create_mode == OS_FILE_OVERWRITE) {
 
241
                create_flag = CREATE_ALWAYS;
 
242
        } else {
 
243
                create_flag = 0;
 
244
                ut_error;
 
245
        }
 
246
 
 
247
        if (purpose == OS_FILE_AIO) {
 
248
                /* use asynchronous (overlapped) io and no buffering
 
249
                of writes in the OS */
 
250
                attributes = 0;
 
251
#ifdef WIN_ASYNC_IO
 
252
                if (os_aio_use_native_aio) {
 
253
                        attributes = attributes | FILE_FLAG_OVERLAPPED;
 
254
                }
 
255
#endif                  
 
256
#ifdef UNIV_NON_BUFFERED_IO
 
257
                attributes = attributes | FILE_FLAG_NO_BUFFERING;
 
258
#endif
 
259
        } else if (purpose == OS_FILE_NORMAL) {
 
260
                attributes = 0
 
261
#ifdef UNIV_NON_BUFFERED_IO
 
262
                         | FILE_FLAG_NO_BUFFERING
 
263
#endif
 
264
                        ;
 
265
        } else {
 
266
                attributes = 0;
 
267
                ut_error;
 
268
        }
 
269
 
 
270
        file = CreateFile(name,
 
271
                        GENERIC_READ | GENERIC_WRITE, /* read and write
 
272
                                                        access */
 
273
                        FILE_SHARE_READ,/* file can be read by other
 
274
                                        processes */
 
275
                        NULL,   /* default security attributes */
 
276
                        create_flag,
 
277
                        attributes,
 
278
                        NULL);  /* no template file */
 
279
 
 
280
        if (file == INVALID_HANDLE_VALUE) {
 
281
                *success = FALSE;
 
282
 
 
283
                if (create_mode != OS_FILE_OPEN
 
284
                    && os_file_get_last_error() == OS_FILE_DISK_FULL) {
 
285
 
 
286
                        retry = os_file_handle_error(file, name);
 
287
 
 
288
                        if (retry) {
 
289
                                goto try_again;
 
290
                        }
 
291
                }
 
292
        } else {
 
293
                *success = TRUE;
 
294
        }
 
295
 
 
296
        return(file);
 
297
#else
 
298
        os_file_t       file;
 
299
        int             create_flag;
 
300
        ibool           retry;
 
301
        
 
302
try_again:      
 
303
        ut_a(name);
 
304
 
 
305
        if (create_mode == OS_FILE_OPEN) {
 
306
                create_flag = O_RDWR;
 
307
        } else if (create_mode == OS_FILE_CREATE) {
 
308
                create_flag = O_RDWR | O_CREAT | O_EXCL;
 
309
        } else if (create_mode == OS_FILE_OVERWRITE) {
 
310
                create_flag = O_RDWR | O_CREAT | O_TRUNC;
 
311
        } else {
 
312
                create_flag = 0;
 
313
                ut_error;
 
314
        }
 
315
 
 
316
        UT_NOT_USED(purpose);
 
317
 
 
318
        if (create_mode == OS_FILE_CREATE) {
 
319
 
 
320
                file = open(name, create_flag, S_IRWXU | S_IRWXG | S_IRWXO);
 
321
        } else {
 
322
                file = open(name, create_flag);
 
323
        }
 
324
        
 
325
        if (file == -1) {
 
326
                *success = FALSE;
 
327
 
 
328
                if (create_mode != OS_FILE_OPEN
 
329
                    && errno == ENOSPC) {
 
330
 
 
331
                        retry = os_file_handle_error(file, name);
 
332
 
 
333
                        if (retry) {
 
334
                                goto try_again;
 
335
                        }
 
336
                }
 
337
        } else {
 
338
                *success = TRUE;
 
339
        }
 
340
 
 
341
        return(file);   
 
342
#endif
 
343
}
 
344
 
 
345
/***************************************************************************
 
346
Closes a file handle. In case of error, error number can be retrieved with
 
347
os_file_get_last_error. */
 
348
 
 
349
ibool
 
350
os_file_close(
 
351
/*==========*/
 
352
                                /* out: TRUE if success */
 
353
        os_file_t       file)   /* in, own: handle to a file */
 
354
{
 
355
#ifdef __WIN__
 
356
        BOOL    ret;
 
357
 
 
358
        ut_a(file);
 
359
 
 
360
        ret = CloseHandle(file);
 
361
 
 
362
        if (ret) {
 
363
                return(TRUE);
 
364
        }
 
365
 
 
366
        return(FALSE);
 
367
#else
 
368
        int     ret;
 
369
 
 
370
        ret = close(file);
 
371
 
 
372
        if (ret == -1) {
 
373
                return(FALSE);
 
374
        }
 
375
 
 
376
        return(TRUE);
 
377
#endif
 
378
}
 
379
 
 
380
/***************************************************************************
 
381
Gets a file size. */
 
382
 
 
383
ibool
 
384
os_file_get_size(
 
385
/*=============*/
 
386
                                /* out: TRUE if success */
 
387
        os_file_t       file,   /* in: handle to a file */
 
388
        ulint*          size,   /* out: least significant 32 bits of file
 
389
                                size */
 
390
        ulint*          size_high)/* out: most significant 32 bits of size */
 
391
{
 
392
#ifdef __WIN__
 
393
        DWORD   high;
 
394
        DWORD   low;
 
395
 
 
396
        low = GetFileSize(file, &high);
 
397
 
 
398
        if ((low == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) {
 
399
                return(FALSE);
 
400
        }
 
401
 
 
402
        *size = low;
 
403
        *size_high = high;
 
404
 
 
405
        return(TRUE);
 
406
#else
 
407
        *size = (ulint) lseek(file, 0, SEEK_END);
 
408
        *size_high = 0;
 
409
        
 
410
        return(TRUE);   
 
411
#endif
 
412
}
 
413
 
 
414
/***************************************************************************
 
415
Sets a file size. This function can be used to extend or truncate a file. */
 
416
 
 
417
ibool
 
418
os_file_set_size(
 
419
/*=============*/
 
420
                                /* out: TRUE if success */
 
421
        char*           name,   /* in: name of the file or path as a
 
422
                                null-terminated string */
 
423
        os_file_t       file,   /* in: handle to a file */
 
424
        ulint           size,   /* in: least significant 32 bits of file
 
425
                                size */
 
426
        ulint           size_high)/* in: most significant 32 bits of size */
 
427
{
 
428
        ulint   offset;
 
429
        ulint   n_bytes;
 
430
        ulint   low;
 
431
        ibool   ret;
 
432
        ibool   retry;
 
433
        ulint   i;
 
434
        byte*   buf;
 
435
 
 
436
try_again:
 
437
        buf = ut_malloc(UNIV_PAGE_SIZE * 64);
 
438
 
 
439
        /* Write buffer full of zeros */
 
440
        for (i = 0; i < UNIV_PAGE_SIZE * 64; i++) {
 
441
                buf[i] = '\0';
 
442
        }
 
443
 
 
444
        offset = 0;
 
445
        low = size;
 
446
#if (UNIV_WORD_SIZE == 8)
 
447
        low = low + (size_high << 32);
 
448
#endif
 
449
        while (offset < low) {
 
450
                if (low - offset < UNIV_PAGE_SIZE * 64) {
 
451
                         n_bytes = low - offset;
 
452
                } else {
 
453
                         n_bytes = UNIV_PAGE_SIZE * 64;
 
454
                }
 
455
          
 
456
                ret = os_file_write(name, file, buf, offset, 0, n_bytes);
 
457
 
 
458
                if (!ret) {
 
459
                        ut_free(buf);
 
460
                        goto error_handling;
 
461
                }
 
462
                offset += n_bytes;
 
463
        }
 
464
 
 
465
        ut_free(buf);
 
466
 
 
467
        ret = os_file_flush(file);
 
468
 
 
469
        if (ret) {
 
470
                return(TRUE);
 
471
        }
 
472
 
 
473
error_handling:
 
474
        retry = os_file_handle_error(file, name); 
 
475
 
 
476
        if (retry) {
 
477
                goto try_again;
 
478
        }
 
479
        
 
480
        ut_error;
 
481
}
 
482
 
 
483
/***************************************************************************
 
484
Flushes the write buffers of a given file to the disk. */
 
485
 
 
486
ibool
 
487
os_file_flush(
 
488
/*==========*/
 
489
                                /* out: TRUE if success */
 
490
        os_file_t       file)   /* in, own: handle to a file */
 
491
{
 
492
#ifdef __WIN__
 
493
        BOOL    ret;
 
494
 
 
495
        ut_a(file);
 
496
 
 
497
        ret = FlushFileBuffers(file);
 
498
 
 
499
        if (ret) {
 
500
                return(TRUE);
 
501
        }
 
502
 
 
503
        return(FALSE);
 
504
#else
 
505
        int     ret;
 
506
        
 
507
        ret = fsync(file);
 
508
 
 
509
        if (ret == 0) {
 
510
                return(TRUE);
 
511
        }
 
512
        
 
513
        return(FALSE);
 
514
#endif
 
515
}
 
516
 
 
517
 
 
518
#ifndef __WIN__
 
519
/***********************************************************************
 
520
Does a synchronous read operation in Posix. */
 
521
static
 
522
ssize_t
 
523
os_file_pread(
 
524
/*==========*/
 
525
                                /* out: number of bytes read, -1 if error */
 
526
        os_file_t       file,   /* in: handle to a file */
 
527
        void*           buf,    /* in: buffer where to read */
 
528
        ulint           n,      /* in: number of bytes to read */       
 
529
        ulint           offset) /* in: offset from where to read */
 
530
{
 
531
#ifdef HAVE_PREAD
 
532
        return(pread(file, buf, n, (off_t) offset));
 
533
#else
 
534
        ssize_t ret;
 
535
        ulint   i;
 
536
 
 
537
        /* Protect the seek / read operation with a mutex */
 
538
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 
539
        
 
540
        os_mutex_enter(os_file_seek_mutexes[i]);
 
541
 
 
542
        ret = lseek(file, (off_t) offset, 0);
 
543
 
 
544
        if (ret < 0) {
 
545
                os_mutex_exit(os_file_seek_mutexes[i]);
 
546
 
 
547
                return(ret);
 
548
        }
 
549
        
 
550
        ret = read(file, buf, n);
 
551
 
 
552
        os_mutex_exit(os_file_seek_mutexes[i]);
 
553
 
 
554
        return(ret);
 
555
#endif
 
556
}
 
557
 
 
558
/***********************************************************************
 
559
Does a synchronous write operation in Posix. */
 
560
static
 
561
ssize_t
 
562
os_file_pwrite(
 
563
/*===========*/
 
564
                                /* out: number of bytes written, -1 if error */
 
565
        os_file_t       file,   /* in: handle to a file */
 
566
        void*           buf,    /* in: buffer from where to write */
 
567
        ulint           n,      /* in: number of bytes to write */      
 
568
        ulint           offset) /* in: offset where to write */
 
569
{
 
570
#ifdef HAVE_PWRITE
 
571
        return(pwrite(file, buf, n, (off_t) offset));
 
572
#else
 
573
        ssize_t ret;
 
574
        ulint   i;
 
575
 
 
576
        /* Protect the seek / write operation with a mutex */
 
577
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 
578
        
 
579
        os_mutex_enter(os_file_seek_mutexes[i]);
 
580
 
 
581
        ret = lseek(file, (off_t) offset, 0);
 
582
 
 
583
        if (ret < 0) {
 
584
                os_mutex_exit(os_file_seek_mutexes[i]);
 
585
 
 
586
                return(ret);
 
587
        }
 
588
        
 
589
        ret = write(file, buf, n);
 
590
 
 
591
        os_mutex_exit(os_file_seek_mutexes[i]);
 
592
 
 
593
        return(ret);
 
594
#endif
 
595
}
 
596
#endif
 
597
 
 
598
/***********************************************************************
 
599
Requests a synchronous positioned read operation. */
 
600
 
 
601
ibool
 
602
os_file_read(
 
603
/*=========*/
 
604
                                /* out: TRUE if request was
 
605
                                successful, FALSE if fail */
 
606
        os_file_t       file,   /* in: handle to a file */
 
607
        void*           buf,    /* in: buffer where to read */
 
608
        ulint           offset, /* in: least significant 32 bits of file
 
609
                                offset where to read */
 
610
        ulint           offset_high, /* in: most significant 32 bits of
 
611
                                offset */
 
612
        ulint           n)      /* in: number of bytes to read */       
 
613
{
 
614
#ifdef __WIN__
 
615
        BOOL            ret;
 
616
        DWORD           len;
 
617
        DWORD           ret2;
 
618
        DWORD           err;
 
619
        DWORD           low;
 
620
        DWORD           high;
 
621
        ibool           retry;
 
622
        ulint           i;
 
623
        
 
624
try_again:      
 
625
        ut_ad(file);
 
626
        ut_ad(buf);
 
627
        ut_ad(n > 0);
 
628
 
 
629
        low = offset;
 
630
        high = offset_high;
 
631
 
 
632
        /* Protect the seek / read operation with a mutex */
 
633
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 
634
        
 
635
        os_mutex_enter(os_file_seek_mutexes[i]);
 
636
 
 
637
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
 
638
 
 
639
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
 
640
                err = GetLastError();
 
641
 
 
642
                os_mutex_exit(os_file_seek_mutexes[i]);
 
643
 
 
644
                goto error_handling;
 
645
        } 
 
646
        
 
647
        ret = ReadFile(file, buf, n, &len, NULL);
 
648
 
 
649
        os_mutex_exit(os_file_seek_mutexes[i]);
 
650
        
 
651
        if (ret && len == n) {
 
652
                return(TRUE);
 
653
        }               
 
654
 
 
655
        err = GetLastError();
 
656
#else
 
657
        ibool   retry;
 
658
        ssize_t ret;
 
659
        ulint   i;
 
660
        
 
661
#if (UNIV_WORD_SIZE == 8)
 
662
        offset = offset + (offset_high << 32);
 
663
#endif  
 
664
try_again:
 
665
        /* Protect the seek / read operation with a mutex */
 
666
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 
667
        
 
668
        os_mutex_enter(os_file_seek_mutexes[i]);
 
669
 
 
670
        ret = os_file_pread(file, buf, n, (off_t) offset);
 
671
 
 
672
        if (ret == n) {
 
673
                os_mutex_exit(os_file_seek_mutexes[i]);
 
674
 
 
675
                return(TRUE);
 
676
        }
 
677
#endif  
 
678
error_handling:
 
679
        retry = os_file_handle_error(file, NULL); 
 
680
 
 
681
        if (retry) {
 
682
                goto try_again;
 
683
        }
 
684
        
 
685
        ut_error;
 
686
 
 
687
        return(FALSE);
 
688
}
 
689
 
 
690
/***********************************************************************
 
691
Requests a synchronous write operation. */
 
692
 
 
693
ibool
 
694
os_file_write(
 
695
/*==========*/
 
696
                                /* out: TRUE if request was
 
697
                                successful, FALSE if fail */
 
698
        char*           name,   /* in: name of the file or path as a
 
699
                                null-terminated string */
 
700
        os_file_t       file,   /* in: handle to a file */
 
701
        void*           buf,    /* in: buffer from which to write */
 
702
        ulint           offset, /* in: least significant 32 bits of file
 
703
                                offset where to write */
 
704
        ulint           offset_high, /* in: most significant 32 bits of
 
705
                                offset */
 
706
        ulint           n)      /* in: number of bytes to write */      
 
707
{
 
708
#ifdef __WIN__
 
709
        BOOL            ret;
 
710
        DWORD           len;
 
711
        DWORD           ret2;
 
712
        DWORD           err;
 
713
        DWORD           low;
 
714
        DWORD           high;
 
715
        ibool           retry;
 
716
        ulint           i;
 
717
 
 
718
try_again:      
 
719
        ut_ad(file);
 
720
        ut_ad(buf);
 
721
        ut_ad(n > 0);
 
722
 
 
723
        low = offset;
 
724
        high = offset_high;
 
725
        
 
726
        /* Protect the seek / write operation with a mutex */
 
727
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 
728
        
 
729
        os_mutex_enter(os_file_seek_mutexes[i]);
 
730
 
 
731
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
 
732
 
 
733
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
 
734
                err = GetLastError();
 
735
 
 
736
                os_mutex_exit(os_file_seek_mutexes[i]);
 
737
                
 
738
                goto error_handling;
 
739
        } 
 
740
 
 
741
        ret = WriteFile(file, buf, n, &len, NULL);
 
742
 
 
743
        os_mutex_exit(os_file_seek_mutexes[i]);
 
744
        
 
745
        if (ret && len == n) {
 
746
                return(TRUE);
 
747
        }
 
748
#else
 
749
        ibool   retry;
 
750
        ssize_t ret;
 
751
        
 
752
#if (UNIV_WORD_SIZE == 8)
 
753
        offset = offset + (offset_high << 32);
 
754
#endif  
 
755
try_again:
 
756
        ret = pwrite(file, buf, n, (off_t) offset);
 
757
 
 
758
        if (ret == n) {
 
759
                return(TRUE);
 
760
        }
 
761
#endif
 
762
                
 
763
error_handling:
 
764
        retry = os_file_handle_error(file, name); 
 
765
 
 
766
        if (retry) {
 
767
                goto try_again;
 
768
        }
 
769
        
 
770
        ut_error;
 
771
 
 
772
        return(FALSE);
 
773
}
 
774
 
 
775
/********************************************************************
 
776
Returns a pointer to the nth slot in the aio array. */
 
777
static
 
778
os_aio_slot_t*
 
779
os_aio_array_get_nth_slot(
 
780
/*======================*/
 
781
                                        /* out: pointer to slot */
 
782
        os_aio_array_t*         array,  /* in: aio array */
 
783
        ulint                   index)  /* in: index of the slot */
 
784
{
 
785
        ut_a(index < array->n_slots);
 
786
 
 
787
        return((array->slots) + index);
 
788
}
 
789
 
 
790
/****************************************************************************
 
791
Creates an aio wait array. */
 
792
static
 
793
os_aio_array_t*
 
794
os_aio_array_create(
 
795
/*================*/
 
796
                                /* out, own: aio array */
 
797
        ulint   n,              /* in: maximum number of pending aio operations
 
798
                                allowed; n must be divisible by n_segments */
 
799
        ulint   n_segments)     /* in: number of segments in the aio array */
 
800
{
 
801
        os_aio_array_t* array;
 
802
        ulint           i;
 
803
        os_aio_slot_t*  slot;
 
804
#ifdef WIN_ASYNC_IO
 
805
        OVERLAPPED*     over;
 
806
#endif  
 
807
        ut_a(n > 0);
 
808
        ut_a(n_segments > 0);
 
809
        ut_a(n % n_segments == 0);
 
810
 
 
811
        array = ut_malloc(sizeof(os_aio_array_t));
 
812
 
 
813
        array->mutex            = os_mutex_create(NULL);
 
814
        array->not_full         = os_event_create(NULL);
 
815
        array->n_slots          = n;
 
816
        array->n_segments       = n_segments;
 
817
        array->n_reserved       = 0;
 
818
        array->slots            = ut_malloc(n * sizeof(os_aio_slot_t));
 
819
        array->events           = ut_malloc(n * sizeof(os_event_t));
 
820
        
 
821
        for (i = 0; i < n; i++) {
 
822
                slot = os_aio_array_get_nth_slot(array, i);
 
823
 
 
824
                slot->pos = i;
 
825
                slot->reserved = FALSE;
 
826
#ifdef WIN_ASYNC_IO
 
827
                over = &(slot->control);
 
828
 
 
829
                over->hEvent = os_event_create(NULL);
 
830
 
 
831
                *((array->events) + i) = over->hEvent;
 
832
#endif
 
833
        }
 
834
        
 
835
        return(array);
 
836
}
 
837
 
 
838
/****************************************************************************
 
839
Initializes the asynchronous io system. Creates separate aio array for
 
840
non-ibuf read and write, a third aio array for the ibuf i/o, with just one
 
841
segment, two aio arrays for log reads and writes with one segment, and a
 
842
synchronous aio array of the specified size. The combined number of segments
 
843
in the three first aio arrays is the parameter n_segments given to the
 
844
function. The caller must create an i/o handler thread for each segment in
 
845
the four first arrays, but not for the sync aio array. */
 
846
 
 
847
void
 
848
os_aio_init(
 
849
/*========*/
 
850
        ulint   n,              /* in: maximum number of pending aio operations
 
851
                                allowed; n must be divisible by n_segments */
 
852
        ulint   n_segments,     /* in: combined number of segments in the four
 
853
                                first aio arrays; must be >= 4 */
 
854
        ulint   n_slots_sync)   /* in: number of slots in the sync aio array */
 
855
{
 
856
        ulint   n_read_segs;
 
857
        ulint   n_write_segs;
 
858
        ulint   n_per_seg;
 
859
        ulint   i;
 
860
#ifdef POSIX_ASYNC_IO
 
861
        sigset_t   sigset;
 
862
#endif
 
863
        ut_ad(n % n_segments == 0);
 
864
        ut_ad(n_segments >= 4);
 
865
 
 
866
        n_per_seg = n / n_segments;
 
867
        n_write_segs = (n_segments - 2) / 2;
 
868
        n_read_segs = n_segments - 2 - n_write_segs;
 
869
        
 
870
        /* printf("Array n per seg %lu\n", n_per_seg); */
 
871
 
 
872
        os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
 
873
                                                        n_read_segs);
 
874
        os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
 
875
                                                        n_write_segs);
 
876
        os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1);
 
877
 
 
878
        os_aio_log_array = os_aio_array_create(n_per_seg, 1);
 
879
 
 
880
        os_aio_sync_array = os_aio_array_create(n_slots_sync, 1);
 
881
 
 
882
        os_aio_n_segments = n_segments;
 
883
 
 
884
        os_aio_validate();
 
885
 
 
886
        for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
 
887
                os_file_seek_mutexes[i] = os_mutex_create(NULL);
 
888
        }
 
889
 
 
890
        os_aio_segment_wait_events = ut_malloc(n_segments * sizeof(void*));
 
891
 
 
892
        for (i = 0; i < n_segments; i++) {
 
893
                os_aio_segment_wait_events[i] = os_event_create(NULL);
 
894
        }
 
895
 
 
896
#ifdef POSIX_ASYNC_IO
 
897
        /* Block aio signals from the current thread and its children:
 
898
        for this to work, the current thread must be the first created
 
899
        in the database, so that all its children will inherit its
 
900
        signal mask */
 
901
        
 
902
        sigemptyset(&sigset);
 
903
        sigaddset(&sigset, SIGRTMIN + 1 + 0);
 
904
        sigaddset(&sigset, SIGRTMIN + 1 + 1);
 
905
        sigaddset(&sigset, SIGRTMIN + 1 + 2);
 
906
        sigaddset(&sigset, SIGRTMIN + 1 + 3);
 
907
 
 
908
        pthread_sigmask(SIG_BLOCK, &sigset, NULL);
 
909
#endif
 
910
}
 
911
                                
 
912
/**************************************************************************
 
913
Calculates segment number for a slot. */
 
914
static
 
915
ulint
 
916
os_aio_get_segment_no_from_slot(
 
917
/*============================*/
 
918
                                /* out: segment number (which is the number
 
919
                                used by, for example, i/o-handler threads) */
 
920
        os_aio_array_t* array,  /* in: aio wait array */
 
921
        os_aio_slot_t*  slot)   /* in: slot in this array */
 
922
{
 
923
        ulint   segment;
 
924
        ulint   seg_len;
 
925
 
 
926
        if (array == os_aio_ibuf_array) {
 
927
                segment = 0;
 
928
 
 
929
        } else if (array == os_aio_log_array) {
 
930
                segment = 1;
 
931
                
 
932
        } else if (array == os_aio_read_array) {
 
933
                seg_len = os_aio_read_array->n_slots /
 
934
                                os_aio_read_array->n_segments;
 
935
 
 
936
                segment = 2 + slot->pos / seg_len;
 
937
        } else {
 
938
                ut_a(array == os_aio_write_array);
 
939
                seg_len = os_aio_write_array->n_slots /
 
940
                                os_aio_write_array->n_segments;
 
941
 
 
942
                segment = os_aio_read_array->n_segments + 2
 
943
                                + slot->pos / seg_len;
 
944
        }
 
945
 
 
946
        return(segment);
 
947
}
 
948
 
 
949
/**************************************************************************
 
950
Calculates local segment number and aio array from global segment number. */
 
951
static
 
952
ulint
 
953
os_aio_get_array_and_local_segment(
 
954
/*===============================*/
 
955
                                        /* out: local segment number within
 
956
                                        the aio array */
 
957
        os_aio_array_t** array,         /* out: aio wait array */
 
958
        ulint            global_segment)/* in: global segment number */
 
959
{
 
960
        ulint   segment;
 
961
 
 
962
        ut_a(global_segment < os_aio_n_segments);       
 
963
 
 
964
        if (global_segment == 0) {
 
965
                *array = os_aio_ibuf_array;
 
966
                segment = 0;
 
967
 
 
968
        } else if (global_segment == 1) {
 
969
                *array = os_aio_log_array;
 
970
                segment = 0;
 
971
                
 
972
        } else if (global_segment < os_aio_read_array->n_segments + 2) {
 
973
                *array = os_aio_read_array;
 
974
 
 
975
                segment = global_segment - 2;
 
976
        } else {
 
977
                *array = os_aio_write_array;
 
978
 
 
979
                segment = global_segment - (os_aio_read_array->n_segments + 2);
 
980
        }
 
981
 
 
982
        return(segment);
 
983
}
 
984
 
 
985
/***********************************************************************
 
986
Gets an integer value designating a specified aio array. This is used
 
987
to give numbers to signals in Posix aio. */
 
988
static
 
989
ulint
 
990
os_aio_get_array_no(
 
991
/*================*/
 
992
        os_aio_array_t* array)  /* in: aio array */
 
993
{       
 
994
        if (array == os_aio_ibuf_array) {
 
995
        
 
996
                return(0);
 
997
 
 
998
        } else if (array == os_aio_log_array) {
 
999
 
 
1000
                return(1);
 
1001
 
 
1002
        } else if (array == os_aio_read_array) {
 
1003
 
 
1004
                return(2);
 
1005
        } else if (array == os_aio_write_array) {
 
1006
 
 
1007
                return(3);
 
1008
        } else {
 
1009
                ut_a(0);
 
1010
 
 
1011
                return(0);
 
1012
        }
 
1013
}
 
1014
 
 
1015
/***********************************************************************
 
1016
Gets the aio array for its number. */
 
1017
static
 
1018
os_aio_array_t*
 
1019
os_aio_get_array_from_no(
 
1020
/*=====================*/
 
1021
                        /* out: aio array */
 
1022
        ulint   n)      /* in: array number */
 
1023
{       
 
1024
        if (n == 0) {
 
1025
                return(os_aio_ibuf_array);
 
1026
        } else if (n == 1) {
 
1027
 
 
1028
                return(os_aio_log_array);
 
1029
        } else if (n == 2) {
 
1030
 
 
1031
                return(os_aio_read_array);
 
1032
        } else if (n == 3) {
 
1033
 
 
1034
                return(os_aio_write_array);
 
1035
        } else {
 
1036
                ut_a(0);
 
1037
 
 
1038
                return(NULL);
 
1039
        }
 
1040
}
 
1041
 
 
1042
/***********************************************************************
 
1043
Requests for a slot in the aio array. If no slot is available, waits until
 
1044
not_full-event becomes signaled. */
 
1045
static
 
1046
os_aio_slot_t*
 
1047
os_aio_array_reserve_slot(
 
1048
/*======================*/
 
1049
                                /* out: pointer to slot */
 
1050
        ulint           type,   /* in: OS_FILE_READ or OS_FILE_WRITE */
 
1051
        os_aio_array_t* array,  /* in: aio array */
 
1052
        void*           message1,/* in: message to be passed along with
 
1053
                                the aio operation */
 
1054
        void*           message2,/* in: message to be passed along with
 
1055
                                the aio operation */
 
1056
        os_file_t       file,   /* in: file handle */
 
1057
        char*           name,   /* in: name of the file or path as a
 
1058
                                null-terminated string */
 
1059
        void*           buf,    /* in: buffer where to read or from which
 
1060
                                to write */
 
1061
        ulint           offset, /* in: least significant 32 bits of file
 
1062
                                offset */
 
1063
        ulint           offset_high, /* in: most significant 32 bits of
 
1064
                                offset */
 
1065
        ulint           len)    /* in: length of the block to read or write */
 
1066
{
 
1067
        os_aio_slot_t*  slot;
 
1068
#ifdef WIN_ASYNC_IO
 
1069
        OVERLAPPED*     control;
 
1070
 
 
1071
#elif defined(POSIX_ASYNC_IO)
 
1072
 
 
1073
        struct aiocb*   control;
 
1074
#endif
 
1075
        ulint           i;
 
1076
loop:
 
1077
        os_mutex_enter(array->mutex);
 
1078
 
 
1079
        if (array->n_reserved == array->n_slots) {
 
1080
                os_mutex_exit(array->mutex);
 
1081
 
 
1082
                if (!os_aio_use_native_aio) {
 
1083
                        /* If the handler threads are suspended, wake them
 
1084
                        so that we get more slots */
 
1085
 
 
1086
                        os_aio_simulated_wake_handler_threads();
 
1087
                }
 
1088
                
 
1089
                os_event_wait(array->not_full);
 
1090
 
 
1091
                goto loop;
 
1092
        }
 
1093
 
 
1094
        for (i = 0;; i++) {
 
1095
                slot = os_aio_array_get_nth_slot(array, i);
 
1096
 
 
1097
                if (slot->reserved == FALSE) {
 
1098
                        break;
 
1099
                }
 
1100
        }
 
1101
 
 
1102
        array->n_reserved++;
 
1103
 
 
1104
        if (array->n_reserved == array->n_slots) {
 
1105
                os_event_reset(array->not_full);
 
1106
        }
 
1107
        
 
1108
        slot->reserved = TRUE;
 
1109
        slot->message1 = message1;
 
1110
        slot->message2 = message2;
 
1111
        slot->file     = file;
 
1112
        slot->name     = name;
 
1113
        slot->len      = len;
 
1114
        slot->type     = type;
 
1115
        slot->buf      = buf;
 
1116
        slot->offset   = offset;
 
1117
        slot->offset_high = offset_high;
 
1118
        slot->io_already_done = FALSE;
 
1119
        
 
1120
#ifdef WIN_ASYNC_IO             
 
1121
        control = &(slot->control);
 
1122
        control->Offset = (DWORD)offset;
 
1123
        control->OffsetHigh = (DWORD)offset_high;
 
1124
        os_event_reset(control->hEvent);
 
1125
 
 
1126
#elif defined(POSIX_ASYNC_IO)
 
1127
 
 
1128
#if (UNIV_WORD_SIZE == 8)
 
1129
        offset = offset + (offset_high << 32);
 
1130
#else
 
1131
        ut_a(offset_high == 0);
 
1132
#endif 
 
1133
        control = &(slot->control);
 
1134
        control->aio_fildes = file;
 
1135
        control->aio_buf = buf;
 
1136
        control->aio_nbytes = len;
 
1137
        control->aio_offset = offset;
 
1138
        control->aio_reqprio = 0;
 
1139
        control->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
 
1140
        control->aio_sigevent.sigev_signo =
 
1141
                        SIGRTMIN + 1 + os_aio_get_array_no(array);
 
1142
                        /* TODO: How to choose the signal numbers? */
 
1143
/*
 
1144
        printf("AIO signal number %lu\n", (ulint) control->aio_sigevent.sigev_signo);
 
1145
*/
 
1146
        control->aio_sigevent.sigev_value.sival_ptr = slot;
 
1147
#endif
 
1148
        os_mutex_exit(array->mutex);
 
1149
 
 
1150
        return(slot);
 
1151
}
 
1152
 
 
1153
/***********************************************************************
 
1154
Frees a slot in the aio array. */
 
1155
static
 
1156
void
 
1157
os_aio_array_free_slot(
 
1158
/*===================*/
 
1159
        os_aio_array_t* array,  /* in: aio array */
 
1160
        os_aio_slot_t*  slot)   /* in: pointer to slot */
 
1161
{
 
1162
        ut_ad(array);
 
1163
        ut_ad(slot);
 
1164
 
 
1165
        os_mutex_enter(array->mutex);
 
1166
 
 
1167
        ut_ad(slot->reserved);
 
1168
        
 
1169
        slot->reserved = FALSE;
 
1170
 
 
1171
        array->n_reserved--;
 
1172
 
 
1173
        if (array->n_reserved == array->n_slots - 1) {
 
1174
                os_event_set(array->not_full);
 
1175
        }
 
1176
 
 
1177
#ifdef WIN_ASYNC_IO             
 
1178
        os_event_reset(slot->control.hEvent);
 
1179
#endif
 
1180
        os_mutex_exit(array->mutex);
 
1181
}
 
1182
 
 
1183
/**************************************************************************
 
1184
Wakes up a simulated aio i/o-handler thread if it has something to do. */
 
1185
static
 
1186
void
 
1187
os_aio_simulated_wake_handler_thread(
 
1188
/*=================================*/
 
1189
        ulint   global_segment) /* in: the number of the segment in the aio
 
1190
                                arrays */
 
1191
{
 
1192
        os_aio_array_t* array;
 
1193
        ulint           segment;
 
1194
        os_aio_slot_t*  slot;
 
1195
        ulint           n;
 
1196
        ulint           i;
 
1197
 
 
1198
        ut_ad(!os_aio_use_native_aio);
 
1199
 
 
1200
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
 
1201
 
 
1202
        n = array->n_slots / array->n_segments;
 
1203
 
 
1204
        /* Look through n slots after the segment * n'th slot */
 
1205
 
 
1206
        os_mutex_enter(array->mutex);
 
1207
 
 
1208
        for (i = 0; i < n; i++) {
 
1209
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
 
1210
 
 
1211
                if (slot->reserved) {
 
1212
                        /* Found an i/o request */
 
1213
                        
 
1214
                        break;
 
1215
                }
 
1216
        }
 
1217
 
 
1218
        os_mutex_exit(array->mutex);
 
1219
 
 
1220
        if (i < n) {
 
1221
                os_event_set(os_aio_segment_wait_events[global_segment]);
 
1222
        }
 
1223
}
 
1224
 
 
1225
/**************************************************************************
 
1226
Wakes up simulated aio i/o-handler threads if they have something to do. */
 
1227
 
 
1228
void
 
1229
os_aio_simulated_wake_handler_threads(void)
 
1230
/*=======================================*/
 
1231
{
 
1232
        ulint   i;
 
1233
 
 
1234
        if (os_aio_use_native_aio) {
 
1235
                /* We do not use simulated aio: do nothing */
 
1236
 
 
1237
                return;
 
1238
        }
 
1239
 
 
1240
        for (i = 0; i < os_aio_n_segments; i++) {
 
1241
                os_aio_simulated_wake_handler_thread(i);
 
1242
        }
 
1243
}
 
1244
 
 
1245
/***********************************************************************
 
1246
Requests an asynchronous i/o operation. */
 
1247
 
 
1248
ibool
 
1249
os_aio(
 
1250
/*===*/
 
1251
                                /* out: TRUE if request was queued
 
1252
                                successfully, FALSE if fail */
 
1253
        ulint           type,   /* in: OS_FILE_READ or OS_FILE_WRITE */
 
1254
        ulint           mode,   /* in: OS_AIO_NORMAL, ..., possibly ORed
 
1255
                                to OS_AIO_SIMULATED_WAKE_LATER: the
 
1256
                                last flag advises this function not to wake
 
1257
                                i/o-handler threads, but the caller will
 
1258
                                do the waking explicitly later, in this
 
1259
                                way the caller can post several requests in
 
1260
                                a batch; NOTE that the batch must not be
 
1261
                                so big that it exhausts the slots in aio
 
1262
                                arrays! NOTE that a simulated batch
 
1263
                                may introduce hidden chances of deadlocks,
 
1264
                                because i/os are not actually handled until
 
1265
                                all have been posted: use with great
 
1266
                                caution! */
 
1267
        char*           name,   /* in: name of the file or path as a
 
1268
                                null-terminated string */
 
1269
        os_file_t       file,   /* in: handle to a file */
 
1270
        void*           buf,    /* in: buffer where to read or from which
 
1271
                                to write */
 
1272
        ulint           offset, /* in: least significant 32 bits of file
 
1273
                                offset where to read or write */
 
1274
        ulint           offset_high, /* in: most significant 32 bits of
 
1275
                                offset */
 
1276
        ulint           n,      /* in: number of bytes to read or write */      
 
1277
        void*           message1,/* in: messages for the aio handler (these
 
1278
                                can be used to identify a completed aio
 
1279
                                operation); if mode is OS_AIO_SYNC, these
 
1280
                                are ignored */
 
1281
        void*           message2)
 
1282
{
 
1283
        os_aio_array_t* array;
 
1284
        os_aio_slot_t*  slot;
 
1285
#ifdef WIN_ASYNC_IO
 
1286
        BOOL            ret             = TRUE;
 
1287
        DWORD           len             = n;
 
1288
        void*           dummy_mess1;
 
1289
        void*           dummy_mess2;
 
1290
#endif
 
1291
        ulint           err             = 0;
 
1292
        ibool           retry;
 
1293
        ulint           wake_later;
 
1294
 
 
1295
        ut_ad(file);
 
1296
        ut_ad(buf);
 
1297
        ut_ad(n > 0);
 
1298
        ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
 
1299
        ut_ad((ulint)buf % OS_FILE_LOG_BLOCK_SIZE == 0)
 
1300
        ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
 
1301
        ut_ad(os_aio_validate());
 
1302
 
 
1303
        wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
 
1304
        mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
 
1305
        
 
1306
        if (mode == OS_AIO_SYNC
 
1307
#ifdef WIN_ASYNC_IO
 
1308
                                && !os_aio_use_native_aio
 
1309
#endif
 
1310
        ) {
 
1311
                /* This is actually an ordinary synchronous read or write:
 
1312
                no need to use an i/o-handler thread. NOTE that if we use
 
1313
                Windows async i/o, Windows does not allow us to use
 
1314
                ordinary synchronous os_file_read etc. on the same file,
 
1315
                therefore we have built a special mechanism for synchronous
 
1316
                wait in the Windows case. */
 
1317
 
 
1318
                if (type == OS_FILE_READ) {
 
1319
                        return(os_file_read(file, buf, offset, offset_high, n));
 
1320
                }
 
1321
 
 
1322
                ut_a(type == OS_FILE_WRITE);
 
1323
 
 
1324
                return(os_file_write(name, file, buf, offset, offset_high, n));
 
1325
        }
 
1326
 
 
1327
try_again:
 
1328
        if (mode == OS_AIO_NORMAL) {
 
1329
                if (type == OS_FILE_READ) {
 
1330
                        array = os_aio_read_array;
 
1331
                } else {
 
1332
                        array = os_aio_write_array;
 
1333
                }
 
1334
        } else if (mode == OS_AIO_IBUF) {
 
1335
                ut_ad(type == OS_FILE_READ);
 
1336
 
 
1337
                array = os_aio_ibuf_array;
 
1338
        } else if (mode == OS_AIO_LOG) {
 
1339
 
 
1340
                array = os_aio_log_array;
 
1341
        } else if (mode == OS_AIO_SYNC) {
 
1342
                array = os_aio_sync_array;
 
1343
        } else {
 
1344
                ut_error;
 
1345
        }
 
1346
        
 
1347
        slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
 
1348
                                        name, buf, offset, offset_high, n);
 
1349
        if (type == OS_FILE_READ) {
 
1350
                if (os_aio_use_native_aio) {
 
1351
#ifdef WIN_ASYNC_IO
 
1352
                        ret = ReadFile(file, buf, (DWORD)n, &len,
 
1353
                                                        &(slot->control));
 
1354
#elif defined(POSIX_ASYNC_IO)
 
1355
                        slot->control.aio_lio_opcode = LIO_READ;
 
1356
                        err = (ulint) aio_read(&(slot->control));
 
1357
                        printf("Starting Posix aio read %lu\n", err);
 
1358
#endif
 
1359
                } else {
 
1360
                        if (!wake_later) {
 
1361
                                os_aio_simulated_wake_handler_thread(
 
1362
                                 os_aio_get_segment_no_from_slot(array, slot));
 
1363
                        }
 
1364
                }
 
1365
        } else if (type == OS_FILE_WRITE) {
 
1366
                if (os_aio_use_native_aio) {
 
1367
#ifdef WIN_ASYNC_IO
 
1368
                        ret = WriteFile(file, buf, (DWORD)n, &len,
 
1369
                                                        &(slot->control));
 
1370
#elif defined(POSIX_ASYNC_IO)
 
1371
                        slot->control.aio_lio_opcode = LIO_WRITE;
 
1372
                        err = (ulint) aio_write(&(slot->control));
 
1373
                        printf("Starting Posix aio write %lu\n", err);
 
1374
#endif
 
1375
                } else {
 
1376
                        if (!wake_later) {
 
1377
                                os_aio_simulated_wake_handler_thread(
 
1378
                                 os_aio_get_segment_no_from_slot(array, slot));
 
1379
                        }
 
1380
                }
 
1381
        } else {
 
1382
                ut_error;
 
1383
        }
 
1384
 
 
1385
#ifdef WIN_ASYNC_IO
 
1386
        if (os_aio_use_native_aio) {
 
1387
                if ((ret && len == n)
 
1388
                        || (!ret && GetLastError() == ERROR_IO_PENDING)) {      
 
1389
 
 
1390
                        /* aio was queued successfully! */
 
1391
                
 
1392
                        if (mode == OS_AIO_SYNC) {
 
1393
                            /* We want a synchronous i/o operation on a file
 
1394
                            where we also use async i/o: in Windows we must
 
1395
                            use the same wait mechanism as for async i/o */
 
1396
                        
 
1397
                            return(os_aio_windows_handle(ULINT_UNDEFINED,
 
1398
                                                slot->pos,
 
1399
                                                &dummy_mess1, &dummy_mess2));
 
1400
                        }
 
1401
 
 
1402
                        return(TRUE);
 
1403
                }
 
1404
 
 
1405
                goto error_handling;
 
1406
        }
 
1407
#endif
 
1408
        if (err == 0) {
 
1409
                /* aio was queued successfully! */
 
1410
 
 
1411
                return(TRUE);
 
1412
        }
 
1413
 
 
1414
error_handling: 
 
1415
        os_aio_array_free_slot(array, slot);
 
1416
 
 
1417
        retry = os_file_handle_error(file, name);
 
1418
 
 
1419
        if (retry) {
 
1420
 
 
1421
                goto try_again;
 
1422
        }       
 
1423
 
 
1424
        ut_error;
 
1425
        
 
1426
        return(FALSE);
 
1427
}
 
1428
 
 
1429
#ifdef WIN_ASYNC_IO
 
1430
/**************************************************************************
 
1431
This function is only used in Windows asynchronous i/o.
 
1432
Waits for an aio operation to complete. This function is used to wait the
 
1433
for completed requests. The aio array of pending requests is divided
 
1434
into segments. The thread specifies which segment or slot it wants to wait
 
1435
for. NOTE: this function will also take care of freeing the aio slot,
 
1436
therefore no other thread is allowed to do the freeing! */
 
1437
 
 
1438
ibool
 
1439
os_aio_windows_handle(
 
1440
/*==================*/
 
1441
                                /* out: TRUE if the aio operation succeeded */
 
1442
        ulint   segment,        /* in: the number of the segment in the aio
 
1443
                                arrays to wait for; segment 0 is the ibuf
 
1444
                                i/o thread, segment 1 the log i/o thread,
 
1445
                                then follow the non-ibuf read threads, and as
 
1446
                                the last are the non-ibuf write threads; if
 
1447
                                this is ULINT_UNDEFINED, then it means that
 
1448
                                sync aio is used, and this parameter is
 
1449
                                ignored */
 
1450
        ulint   pos,            /* this parameter is used only in sync aio:
 
1451
                                wait for the aio slot at this position */  
 
1452
        void**  message1,       /* out: the messages passed with the aio
 
1453
                                request; note that also in the case where
 
1454
                                the aio operation failed, these output
 
1455
                                parameters are valid and can be used to
 
1456
                                restart the operation, for example */
 
1457
        void**  message2)
 
1458
{
 
1459
        os_aio_array_t* array;
 
1460
        os_aio_slot_t*  slot;
 
1461
        ulint           n;
 
1462
        ulint           i;
 
1463
        ibool           ret_val;
 
1464
        ulint           err;
 
1465
        BOOL            ret;
 
1466
        DWORD           len;
 
1467
 
 
1468
        if (segment == ULINT_UNDEFINED) {
 
1469
                array = os_aio_sync_array;
 
1470
                segment = 0;
 
1471
        } else {
 
1472
                segment = os_aio_get_array_and_local_segment(&array, segment);
 
1473
        }
 
1474
        
 
1475
        /* NOTE! We only access constant fields in os_aio_array. Therefore
 
1476
        we do not have to acquire the protecting mutex yet */
 
1477
 
 
1478
        ut_ad(os_aio_validate());
 
1479
        ut_ad(segment < array->n_segments);
 
1480
 
 
1481
        n = array->n_slots / array->n_segments;
 
1482
 
 
1483
        if (array == os_aio_sync_array) {
 
1484
                ut_ad(pos < array->n_slots); 
 
1485
                os_event_wait(array->events[pos]);
 
1486
                i = pos;
 
1487
        } else {
 
1488
                i = os_event_wait_multiple(n, (array->events) + segment * n);
 
1489
        }
 
1490
 
 
1491
        os_mutex_enter(array->mutex);
 
1492
 
 
1493
        slot = os_aio_array_get_nth_slot(array, i + segment * n);
 
1494
 
 
1495
        ut_a(slot->reserved);
 
1496
 
 
1497
        ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
 
1498
 
 
1499
        *message1 = slot->message1;
 
1500
        *message2 = slot->message2;
 
1501
 
 
1502
        if (ret && len == slot->len) {
 
1503
                ret_val = TRUE;
 
1504
        } else {
 
1505
                err = GetLastError();
 
1506
                ut_error;
 
1507
 
 
1508
                ret_val = FALSE;
 
1509
        }                 
 
1510
 
 
1511
        os_mutex_exit(array->mutex);
 
1512
 
 
1513
        os_aio_array_free_slot(array, slot);
 
1514
        
 
1515
        return(ret_val);
 
1516
}
 
1517
#endif
 
1518
 
 
1519
#ifdef POSIX_ASYNC_IO
 
1520
 
 
1521
/**************************************************************************
 
1522
This function is only used in Posix asynchronous i/o. Waits for an aio
 
1523
operation to complete. */
 
1524
 
 
1525
ibool
 
1526
os_aio_posix_handle(
 
1527
/*================*/
 
1528
                                /* out: TRUE if the aio operation succeeded */
 
1529
        ulint   array_no,       /* in: array number 0 - 3 */
 
1530
        void**  message1,       /* out: the messages passed with the aio
 
1531
                                request; note that also in the case where
 
1532
                                the aio operation failed, these output
 
1533
                                parameters are valid and can be used to
 
1534
                                restart the operation, for example */
 
1535
        void**  message2)
 
1536
{
 
1537
        os_aio_array_t* array;
 
1538
        os_aio_slot_t*  slot;
 
1539
        siginfo_t       info;
 
1540
        sigset_t        sigset;
 
1541
        sigset_t        proc_sigset;
 
1542
        sigset_t        thr_sigset;
 
1543
        int             ret;
 
1544
        int             i;
 
1545
        int             sig;
 
1546
        
 
1547
        sigemptyset(&sigset);
 
1548
        sigaddset(&sigset, SIGRTMIN + 1 + array_no);
 
1549
 
 
1550
        pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
 
1551
 
 
1552
        /*
 
1553
        sigprocmask(0, NULL, &proc_sigset);
 
1554
        pthread_sigmask(0, NULL, &thr_sigset);
 
1555
 
 
1556
        for (i = 32 ; i < 40; i++) {
 
1557
          printf("%lu : %lu %lu\n", (ulint)i,
 
1558
                 (ulint)sigismember(&proc_sigset, i),
 
1559
                 (ulint)sigismember(&thr_sigset, i));
 
1560
        }
 
1561
        */
 
1562
 
 
1563
        ret = sigwaitinfo(&sigset, &info);
 
1564
 
 
1565
        if (sig != SIGRTMIN + 1 + array_no) {
 
1566
 
 
1567
                ut_a(0);
 
1568
        
 
1569
                return(FALSE);
 
1570
        }
 
1571
        
 
1572
        printf("Handling Posix aio\n");
 
1573
 
 
1574
        array = os_aio_get_array_from_no(array_no);
 
1575
 
 
1576
        os_mutex_enter(array->mutex);
 
1577
 
 
1578
        slot = info.si_value.sival_ptr;
 
1579
 
 
1580
        ut_a(slot->reserved);
 
1581
 
 
1582
        *message1 = slot->message1;
 
1583
        *message2 = slot->message2;
 
1584
 
 
1585
        os_mutex_exit(array->mutex);
 
1586
 
 
1587
        os_aio_array_free_slot(array, slot);
 
1588
        
 
1589
        return(TRUE);
 
1590
}
 
1591
#endif
 
1592
 
 
1593
/**************************************************************************
 
1594
Does simulated aio. This function should be called by an i/o-handler
 
1595
thread. */
 
1596
 
 
1597
ibool
 
1598
os_aio_simulated_handle(
 
1599
/*====================*/
 
1600
                                /* out: TRUE if the aio operation succeeded */
 
1601
        ulint   global_segment, /* in: the number of the segment in the aio
 
1602
                                arrays to wait for; segment 0 is the ibuf
 
1603
                                i/o thread, segment 1 the log i/o thread,
 
1604
                                then follow the non-ibuf read threads, and as
 
1605
                                the last are the non-ibuf write threads */
 
1606
        void**  message1,       /* out: the messages passed with the aio
 
1607
                                request; note that also in the case where
 
1608
                                the aio operation failed, these output
 
1609
                                parameters are valid and can be used to
 
1610
                                restart the operation, for example */
 
1611
        void**  message2)
 
1612
{
 
1613
        os_aio_array_t* array;
 
1614
        ulint           segment;
 
1615
        os_aio_slot_t*  slot;
 
1616
        os_aio_slot_t*  slot2;
 
1617
        os_aio_slot_t*  consecutive_ios[OS_AIO_MERGE_N_CONSECUTIVE];
 
1618
        ulint           n_consecutive;
 
1619
        ulint           total_len;
 
1620
        ulint           offs;
 
1621
        ulint           lowest_offset;
 
1622
        byte*           combined_buf;
 
1623
        ibool           ret;
 
1624
        ulint           n;
 
1625
        ulint           i;
 
1626
 
 
1627
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
 
1628
        
 
1629
restart:
 
1630
        /* Give other threads chance to add several i/os to the array
 
1631
        at once */
 
1632
        
 
1633
        os_thread_yield();
 
1634
 
 
1635
        /* NOTE! We only access constant fields in os_aio_array. Therefore
 
1636
        we do not have to acquire the protecting mutex yet */
 
1637
 
 
1638
        ut_ad(os_aio_validate());
 
1639
        ut_ad(segment < array->n_segments);
 
1640
 
 
1641
        n = array->n_slots / array->n_segments;
 
1642
 
 
1643
        /* Look through n slots after the segment * n'th slot */
 
1644
 
 
1645
        os_mutex_enter(array->mutex);
 
1646
 
 
1647
        /* Check if there is a slot for which the i/o has already been
 
1648
        done */
 
1649
        
 
1650
        for (i = 0; i < n; i++) {
 
1651
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
 
1652
 
 
1653
                if (slot->reserved && slot->io_already_done) {
 
1654
 
 
1655
                        ret = TRUE;
 
1656
                        
 
1657
                        goto slot_io_done;
 
1658
                }
 
1659
        }
 
1660
 
 
1661
        n_consecutive = 0;
 
1662
 
 
1663
        /* Look for an i/o request at the lowest offset in the array */
 
1664
 
 
1665
        lowest_offset = ULINT_MAX;
 
1666
        
 
1667
        for (i = 0; i < n; i++) {
 
1668
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
 
1669
 
 
1670
                if (slot->reserved && slot->offset < lowest_offset) {
 
1671
 
 
1672
                        /* Found an i/o request */
 
1673
                        consecutive_ios[0] = slot;
 
1674
 
 
1675
                        n_consecutive = 1;
 
1676
 
 
1677
                        lowest_offset = slot->offset;
 
1678
                }
 
1679
        }
 
1680
 
 
1681
        if (n_consecutive == 0) {
 
1682
 
 
1683
                /* No i/o requested at the moment */
 
1684
 
 
1685
                goto wait_for_io;
 
1686
        }
 
1687
 
 
1688
        slot = consecutive_ios[0];
 
1689
 
 
1690
        /* Check if there are several consecutive blocks to read or write */
 
1691
 
 
1692
consecutive_loop:       
 
1693
        for (i = 0; i < n; i++) {
 
1694
                slot2 = os_aio_array_get_nth_slot(array, i + segment * n);
 
1695
 
 
1696
                if (slot2->reserved && slot2 != slot
 
1697
                    && slot2->offset == slot->offset + slot->len
 
1698
                    && slot->offset + slot->len > slot->offset /* check that
 
1699
                                                sum does not wrap over */
 
1700
                    && slot2->offset_high == slot->offset_high
 
1701
                    && slot2->type == slot->type
 
1702
                    && slot2->file == slot->file) {
 
1703
 
 
1704
                        /* Found a consecutive i/o request */
 
1705
 
 
1706
                        consecutive_ios[n_consecutive] = slot2;
 
1707
                        n_consecutive++;
 
1708
 
 
1709
                        slot = slot2;
 
1710
 
 
1711
                        if (n_consecutive < OS_AIO_MERGE_N_CONSECUTIVE) {
 
1712
                        
 
1713
                                goto consecutive_loop;
 
1714
                        } else {
 
1715
                                break;
 
1716
                        }
 
1717
                }
 
1718
        }
 
1719
 
 
1720
        /* We have now collected n_consecutive i/o requests in the array;
 
1721
        allocate a single buffer which can hold all data, and perform the
 
1722
        i/o */
 
1723
 
 
1724
        total_len = 0;
 
1725
        slot = consecutive_ios[0];
 
1726
        
 
1727
        for (i = 0; i < n_consecutive; i++) {
 
1728
                total_len += consecutive_ios[i]->len;
 
1729
        }
 
1730
 
 
1731
        if (n_consecutive == 1) {
 
1732
                /* We can use the buffer of the i/o request */
 
1733
                combined_buf = slot->buf;
 
1734
        } else {
 
1735
                combined_buf = ut_malloc(total_len);
 
1736
 
 
1737
                ut_a(combined_buf);
 
1738
        }
 
1739
        
 
1740
        /* We release the array mutex for the time of the i/o: NOTE that
 
1741
        this assumes that there is just one i/o-handler thread serving
 
1742
        a single segment of slots! */
 
1743
 
 
1744
        os_mutex_exit(array->mutex);
 
1745
 
 
1746
        if (slot->type == OS_FILE_WRITE && n_consecutive > 1) {
 
1747
                /* Copy the buffers to the combined buffer */
 
1748
                offs = 0;
 
1749
                
 
1750
                for (i = 0; i < n_consecutive; i++) {
 
1751
 
 
1752
                        ut_memcpy(combined_buf + offs, consecutive_ios[i]->buf,
 
1753
                                                consecutive_ios[i]->len);
 
1754
                        offs += consecutive_ios[i]->len;
 
1755
                }
 
1756
        }
 
1757
 
 
1758
        /* Do the i/o with ordinary, synchronous i/o functions: */
 
1759
        if (slot->type == OS_FILE_WRITE) {
 
1760
                ret = os_file_write(slot->name, slot->file, combined_buf,
 
1761
                                slot->offset, slot->offset_high, total_len);
 
1762
        } else {
 
1763
                ret = os_file_read(slot->file, combined_buf,
 
1764
                                slot->offset, slot->offset_high, total_len);
 
1765
        }
 
1766
 
 
1767
        ut_a(ret);
 
1768
        
 
1769
/* printf("aio: %lu consecutive %lu:th segment, first offs %lu blocks\n",
 
1770
                        n_consecutive, global_segment, slot->offset
 
1771
                                        / UNIV_PAGE_SIZE); */
 
1772
 
 
1773
        if (slot->type == OS_FILE_READ && n_consecutive > 1) {
 
1774
                /* Copy the combined buffer to individual buffers */
 
1775
                offs = 0;
 
1776
                
 
1777
                for (i = 0; i < n_consecutive; i++) {
 
1778
 
 
1779
                        ut_memcpy(consecutive_ios[i]->buf, combined_buf + offs, 
 
1780
                                                consecutive_ios[i]->len);
 
1781
                        offs += consecutive_ios[i]->len;
 
1782
                }
 
1783
        }
 
1784
 
 
1785
        if (n_consecutive > 1) {
 
1786
                ut_free(combined_buf);
 
1787
        }
 
1788
 
 
1789
        os_mutex_enter(array->mutex);
 
1790
 
 
1791
        /* Mark the i/os done in slots */
 
1792
 
 
1793
        for (i = 0; i < n_consecutive; i++) {
 
1794
                consecutive_ios[i]->io_already_done = TRUE;
 
1795
        }
 
1796
 
 
1797
        /* We return the messages for the first slot now, and if there were
 
1798
        several slots, the messages will be returned with subsequent calls
 
1799
        of this function */
 
1800
        
 
1801
slot_io_done:
 
1802
 
 
1803
        ut_a(slot->reserved);
 
1804
 
 
1805
        *message1 = slot->message1;
 
1806
        *message2 = slot->message2;
 
1807
 
 
1808
        os_mutex_exit(array->mutex);
 
1809
 
 
1810
        os_aio_array_free_slot(array, slot);
 
1811
        
 
1812
        return(ret);
 
1813
 
 
1814
wait_for_io:
 
1815
        /* We wait here until there again can be i/os in the segment
 
1816
        of this thread */
 
1817
        
 
1818
        os_event_reset(os_aio_segment_wait_events[global_segment]);
 
1819
 
 
1820
        os_mutex_exit(array->mutex);
 
1821
 
 
1822
        os_event_wait(os_aio_segment_wait_events[global_segment]);
 
1823
 
 
1824
        goto restart;
 
1825
}
 
1826
 
 
1827
/**************************************************************************
 
1828
Validates the consistency of an aio array. */
 
1829
static
 
1830
ibool
 
1831
os_aio_array_validate(
 
1832
/*==================*/
 
1833
                                /* out: TRUE if ok */
 
1834
        os_aio_array_t* array)  /* in: aio wait array */
 
1835
{
 
1836
        os_aio_slot_t*  slot;
 
1837
        ulint           n_reserved      = 0;
 
1838
        ulint           i;
 
1839
        
 
1840
        ut_a(array);
 
1841
 
 
1842
        os_mutex_enter(array->mutex);
 
1843
 
 
1844
        ut_a(array->n_slots > 0);
 
1845
        ut_a(array->n_segments > 0);
 
1846
        
 
1847
        for (i = 0; i < array->n_slots; i++) {
 
1848
                slot = os_aio_array_get_nth_slot(array, i);
 
1849
        
 
1850
                if (slot->reserved) {
 
1851
                        n_reserved++;
 
1852
                        ut_a(slot->len > 0);
 
1853
                }
 
1854
        }
 
1855
 
 
1856
        ut_a(array->n_reserved == n_reserved);
 
1857
 
 
1858
        os_mutex_exit(array->mutex);
 
1859
 
 
1860
        return(TRUE);
 
1861
}
 
1862
 
 
1863
/**************************************************************************
 
1864
Validates the consistency the aio system. */
 
1865
 
 
1866
ibool
 
1867
os_aio_validate(void)
 
1868
/*=================*/
 
1869
                                /* out: TRUE if ok */
 
1870
{
 
1871
        os_aio_array_validate(os_aio_read_array);
 
1872
        os_aio_array_validate(os_aio_write_array);
 
1873
        os_aio_array_validate(os_aio_ibuf_array);
 
1874
        os_aio_array_validate(os_aio_log_array);
 
1875
        os_aio_array_validate(os_aio_sync_array);
 
1876
 
 
1877
        return(TRUE);
 
1878
}
 
1879
 
 
1880
/**************************************************************************
 
1881
Prints info of the aio arrays. */
 
1882
 
 
1883
void
 
1884
os_aio_print(void)
 
1885
/*==============*/
 
1886
{
 
1887
        os_aio_array_t* array;
 
1888
        os_aio_slot_t*  slot;
 
1889
        ulint           n_reserved;
 
1890
        ulint           i;
 
1891
        
 
1892
        array = os_aio_read_array;
 
1893
loop:
 
1894
        ut_a(array);
 
1895
        
 
1896
        printf("INFO OF AN AIO ARRAY\n");
 
1897
 
 
1898
        os_mutex_enter(array->mutex);
 
1899
 
 
1900
        ut_a(array->n_slots > 0);
 
1901
        ut_a(array->n_segments > 0);
 
1902
        
 
1903
        n_reserved = 0;
 
1904
 
 
1905
        for (i = 0; i < array->n_slots; i++) {
 
1906
                slot = os_aio_array_get_nth_slot(array, i);
 
1907
        
 
1908
                if (slot->reserved) {
 
1909
                        n_reserved++;
 
1910
                        printf("Reserved slot, messages %lx %lx\n",
 
1911
                                        slot->message1, slot->message2);
 
1912
                        ut_a(slot->len > 0);
 
1913
                }
 
1914
        }
 
1915
 
 
1916
        ut_a(array->n_reserved == n_reserved);
 
1917
 
 
1918
        printf("Total of %lu reserved aio slots\n", n_reserved);
 
1919
        
 
1920
        os_mutex_exit(array->mutex);
 
1921
 
 
1922
        if (array == os_aio_read_array) {
 
1923
                array = os_aio_write_array;
 
1924
 
 
1925
                goto loop;
 
1926
        }
 
1927
 
 
1928
        if (array == os_aio_write_array) {
 
1929
                array = os_aio_ibuf_array;
 
1930
 
 
1931
                goto loop;
 
1932
        }
 
1933
 
 
1934
        if (array == os_aio_ibuf_array) {
 
1935
                array = os_aio_log_array;
 
1936
 
 
1937
                goto loop;
 
1938
        }
 
1939
 
 
1940
        if (array == os_aio_log_array) {
 
1941
                array = os_aio_sync_array;
 
1942
 
 
1943
                goto loop;
 
1944
        }
 
1945
}
 
1946
 
 
1947
/**************************************************************************
 
1948
Checks that all slots in the system have been freed, that is, there are
 
1949
no pending io operations. */
 
1950
 
 
1951
ibool
 
1952
os_aio_all_slots_free(void)
 
1953
/*=======================*/
 
1954
                                /* out: TRUE if all free */
 
1955
{
 
1956
        os_aio_array_t* array;
 
1957
        ulint           n_res   = 0;
 
1958
        
 
1959
        array = os_aio_read_array;
 
1960
 
 
1961
        os_mutex_enter(array->mutex);
 
1962
 
 
1963
        n_res += array->n_reserved; 
 
1964
        
 
1965
        os_mutex_exit(array->mutex);
 
1966
 
 
1967
        array = os_aio_write_array;
 
1968
 
 
1969
        os_mutex_enter(array->mutex);
 
1970
 
 
1971
        n_res += array->n_reserved; 
 
1972
        
 
1973
        os_mutex_exit(array->mutex);
 
1974
 
 
1975
        array = os_aio_ibuf_array;
 
1976
 
 
1977
        os_mutex_enter(array->mutex);
 
1978
 
 
1979
        n_res += array->n_reserved; 
 
1980
        
 
1981
        os_mutex_exit(array->mutex);
 
1982
 
 
1983
        array = os_aio_log_array;
 
1984
 
 
1985
        os_mutex_enter(array->mutex);
 
1986
 
 
1987
        n_res += array->n_reserved; 
 
1988
        
 
1989
        os_mutex_exit(array->mutex);
 
1990
 
 
1991
        array = os_aio_sync_array;
 
1992
 
 
1993
        os_mutex_enter(array->mutex);
 
1994
 
 
1995
        n_res += array->n_reserved; 
 
1996
        
 
1997
        os_mutex_exit(array->mutex);
 
1998
 
 
1999
        if (n_res == 0) {
 
2000
 
 
2001
                return(TRUE);
 
2002
        }
 
2003
 
 
2004
        return(FALSE);
 
2005
}