~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/buf/buf0rea.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
The database buffer read
 
3
 
 
4
(c) 1995 Innobase Oy
 
5
 
 
6
Created 11/5/1995 Heikki Tuuri
 
7
*******************************************************/
 
8
 
 
9
#include "buf0rea.h"
 
10
 
 
11
#include "fil0fil.h"
 
12
#include "mtr0mtr.h"
 
13
 
 
14
#include "buf0buf.h"
 
15
#include "buf0flu.h"
 
16
#include "buf0lru.h"
 
17
#include "ibuf0ibuf.h"
 
18
#include "log0recv.h"
 
19
#include "trx0sys.h"
 
20
#include "os0file.h"
 
21
#include "srv0start.h"
 
22
 
 
23
extern ulint srv_read_ahead_rnd;
 
24
extern ulint srv_read_ahead_seq;
 
25
extern ulint srv_buf_pool_reads;
 
26
 
 
27
/* The size in blocks of the area where the random read-ahead algorithm counts
 
28
the accessed pages when deciding whether to read-ahead */
 
29
#define BUF_READ_AHEAD_RANDOM_AREA      BUF_READ_AHEAD_AREA
 
30
 
 
31
/* There must be at least this many pages in buf_pool in the area to start
 
32
a random read-ahead */
 
33
#define BUF_READ_AHEAD_RANDOM_THRESHOLD (5 + BUF_READ_AHEAD_RANDOM_AREA / 8)
 
34
 
 
35
/* The linear read-ahead area size */
 
36
#define BUF_READ_AHEAD_LINEAR_AREA      BUF_READ_AHEAD_AREA
 
37
 
 
38
/* The linear read-ahead threshold */
 
39
#define BUF_READ_AHEAD_LINEAR_THRESHOLD (3 * BUF_READ_AHEAD_LINEAR_AREA / 8)
 
40
 
 
41
/* If there are buf_pool->curr_size per the number below pending reads, then
 
42
read-ahead is not done: this is to prevent flooding the buffer pool with
 
43
i/o-fixed buffer blocks */
 
44
#define BUF_READ_AHEAD_PEND_LIMIT       2
 
45
 
 
46
/************************************************************************
 
47
Low-level function which reads a page asynchronously from a file to the
 
48
buffer buf_pool if it is not already there, in which case does nothing.
 
49
Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
 
50
flag is cleared and the x-lock released by an i/o-handler thread. */
 
51
static
 
52
ulint
 
53
buf_read_page_low(
 
54
/*==============*/
 
55
                        /* out: 1 if a read request was queued, 0 if the page
 
56
                        already resided in buf_pool, or if the page is in
 
57
                        the doublewrite buffer blocks in which case it is never
 
58
                        read into the pool, or if the tablespace does not
 
59
                        exist or is being dropped */
 
60
        ulint*  err,    /* out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
 
61
                        trying to read from a non-existent tablespace, or a
 
62
                        tablespace which is just now being dropped */
 
63
        ibool   sync,   /* in: TRUE if synchronous aio is desired */
 
64
        ulint   mode,   /* in: BUF_READ_IBUF_PAGES_ONLY, ...,
 
65
                        ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
 
66
                        at read-ahead functions) */
 
67
        ulint   space,  /* in: space id */
 
68
        ib_longlong tablespace_version, /* in: if the space memory object has
 
69
                        this timestamp different from what we are giving here,
 
70
                        treat the tablespace as dropped; this is a timestamp we
 
71
                        use to stop dangling page reads from a tablespace
 
72
                        which we have DISCARDed + IMPORTed back */
 
73
        ulint   offset) /* in: page number */
 
74
{
 
75
        buf_block_t*    block;
 
76
        ulint           wake_later;
 
77
 
 
78
        *err = DB_SUCCESS;
 
79
 
 
80
        wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
 
81
        mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER;
 
82
 
 
83
        if (trx_doublewrite && space == TRX_SYS_SPACE
 
84
            && (   (offset >= trx_doublewrite->block1
 
85
                    && offset < trx_doublewrite->block1
 
86
                    + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
 
87
                   || (offset >= trx_doublewrite->block2
 
88
                       && offset < trx_doublewrite->block2
 
89
                       + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) {
 
90
                ut_print_timestamp(stderr);
 
91
                fprintf(stderr,
 
92
                        "  InnoDB: Warning: trying to read"
 
93
                        " doublewrite buffer page %lu\n",
 
94
                        (ulong) offset);
 
95
 
 
96
                return(0);
 
97
        }
 
98
 
 
99
        if (ibuf_bitmap_page(offset) || trx_sys_hdr_page(space, offset)) {
 
100
 
 
101
                /* Trx sys header is so low in the latching order that we play
 
102
                safe and do not leave the i/o-completion to an asynchronous
 
103
                i/o-thread. Ibuf bitmap pages must always be read with
 
104
                syncronous i/o, to make sure they do not get involved in
 
105
                thread deadlocks. */
 
106
 
 
107
                sync = TRUE;
 
108
        }
 
109
 
 
110
        /* The following call will also check if the tablespace does not exist
 
111
        or is being dropped; if we succeed in initing the page in the buffer
 
112
        pool for read, then DISCARD cannot proceed until the read has
 
113
        completed */
 
114
        block = buf_page_init_for_read(err, mode, space, tablespace_version,
 
115
                                       offset);
 
116
        if (block == NULL) {
 
117
 
 
118
                return(0);
 
119
        }
 
120
 
 
121
#ifdef UNIV_DEBUG
 
122
        if (buf_debug_prints) {
 
123
                fprintf(stderr,
 
124
                        "Posting read request for page %lu, sync %lu\n",
 
125
                        (ulong) offset,
 
126
                        (ulong) sync);
 
127
        }
 
128
#endif
 
129
 
 
130
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
131
 
 
132
        *err = fil_io(OS_FILE_READ | wake_later,
 
133
                      sync, space,
 
134
                      offset, 0, UNIV_PAGE_SIZE,
 
135
                      (void*)block->frame, (void*)block);
 
136
        ut_a(*err == DB_SUCCESS);
 
137
 
 
138
        if (sync) {
 
139
                /* The i/o is already completed when we arrive from
 
140
                fil_read */
 
141
                buf_page_io_complete(block);
 
142
        }
 
143
 
 
144
        return(1);
 
145
}
 
146
 
 
147
/************************************************************************
 
148
Applies a random read-ahead in buf_pool if there are at least a threshold
 
149
value of accessed pages from the random read-ahead area. Does not read any
 
150
page, not even the one at the position (space, offset), if the read-ahead
 
151
mechanism is not activated. NOTE 1: the calling thread may own latches on
 
152
pages: to avoid deadlocks this function must be written such that it cannot
 
153
end up waiting for these latches! NOTE 2: the calling thread must want
 
154
access to the page given: this rule is set to prevent unintended read-aheads
 
155
performed by ibuf routines, a situation which could result in a deadlock if
 
156
the OS does not support asynchronous i/o. */
 
157
static
 
158
ulint
 
159
buf_read_ahead_random(
 
160
/*==================*/
 
161
                        /* out: number of page read requests issued; NOTE
 
162
                        that if we read ibuf pages, it may happen that
 
163
                        the page at the given page number does not get
 
164
                        read even if we return a value > 0! */
 
165
        ulint   space,  /* in: space id */
 
166
        ulint   offset) /* in: page number of a page which the current thread
 
167
                        wants to access */
 
168
{
 
169
        ib_longlong     tablespace_version;
 
170
        buf_block_t*    block;
 
171
        ulint           recent_blocks   = 0;
 
172
        ulint           count;
 
173
        ulint           LRU_recent_limit;
 
174
        ulint           ibuf_mode;
 
175
        ulint           low, high;
 
176
        ulint           err;
 
177
        ulint           i;
 
178
 
 
179
        if (srv_startup_is_before_trx_rollback_phase) {
 
180
                /* No read-ahead to avoid thread deadlocks */
 
181
                return(0);
 
182
        }
 
183
 
 
184
        if (ibuf_bitmap_page(offset) || trx_sys_hdr_page(space, offset)) {
 
185
 
 
186
                /* If it is an ibuf bitmap page or trx sys hdr, we do
 
187
                no read-ahead, as that could break the ibuf page access
 
188
                order */
 
189
 
 
190
                return(0);
 
191
        }
 
192
 
 
193
        /* Remember the tablespace version before we ask te tablespace size
 
194
        below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
 
195
        do not try to read outside the bounds of the tablespace! */
 
196
 
 
197
        tablespace_version = fil_space_get_version(space);
 
198
 
 
199
        low  = (offset / BUF_READ_AHEAD_RANDOM_AREA)
 
200
                * BUF_READ_AHEAD_RANDOM_AREA;
 
201
        high = (offset / BUF_READ_AHEAD_RANDOM_AREA + 1)
 
202
                * BUF_READ_AHEAD_RANDOM_AREA;
 
203
        if (high > fil_space_get_size(space)) {
 
204
 
 
205
                high = fil_space_get_size(space);
 
206
        }
 
207
 
 
208
        /* Get the minimum LRU_position field value for an initial segment
 
209
        of the LRU list, to determine which blocks have recently been added
 
210
        to the start of the list. */
 
211
 
 
212
        LRU_recent_limit = buf_LRU_get_recent_limit();
 
213
 
 
214
        mutex_enter(&(buf_pool->mutex));
 
215
 
 
216
        if (buf_pool->n_pend_reads
 
217
            > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
 
218
                mutex_exit(&(buf_pool->mutex));
 
219
 
 
220
                return(0);
 
221
        }
 
222
 
 
223
        /* Count how many blocks in the area have been recently accessed,
 
224
        that is, reside near the start of the LRU list. */
 
225
 
 
226
        for (i = low; i < high; i++) {
 
227
                block = buf_page_hash_get(space, i);
 
228
 
 
229
                if ((block)
 
230
                    && (block->LRU_position > LRU_recent_limit)
 
231
                    && block->accessed) {
 
232
 
 
233
                        recent_blocks++;
 
234
                }
 
235
        }
 
236
 
 
237
        mutex_exit(&(buf_pool->mutex));
 
238
 
 
239
        if (recent_blocks < BUF_READ_AHEAD_RANDOM_THRESHOLD) {
 
240
                /* Do nothing */
 
241
 
 
242
                return(0);
 
243
        }
 
244
 
 
245
        /* Read all the suitable blocks within the area */
 
246
 
 
247
        if (ibuf_inside()) {
 
248
                ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
 
249
        } else {
 
250
                ibuf_mode = BUF_READ_ANY_PAGE;
 
251
        }
 
252
 
 
253
        count = 0;
 
254
 
 
255
        for (i = low; i < high; i++) {
 
256
                /* It is only sensible to do read-ahead in the non-sync aio
 
257
                mode: hence FALSE as the first parameter */
 
258
 
 
259
                if (!ibuf_bitmap_page(i)) {
 
260
                        count += buf_read_page_low(
 
261
                                &err, FALSE,
 
262
                                ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
 
263
                                space, tablespace_version, i);
 
264
                        if (err == DB_TABLESPACE_DELETED) {
 
265
                                ut_print_timestamp(stderr);
 
266
                                fprintf(stderr,
 
267
                                        "  InnoDB: Warning: in random"
 
268
                                        " readahead trying to access\n"
 
269
                                        "InnoDB: tablespace %lu page %lu,\n"
 
270
                                        "InnoDB: but the tablespace does not"
 
271
                                        " exist or is just being dropped.\n",
 
272
                                        (ulong) space, (ulong) i);
 
273
                        }
 
274
                }
 
275
        }
 
276
 
 
277
        /* In simulated aio we wake the aio handler threads only after
 
278
        queuing all aio requests, in native aio the following call does
 
279
        nothing: */
 
280
 
 
281
        os_aio_simulated_wake_handler_threads();
 
282
 
 
283
#ifdef UNIV_DEBUG
 
284
        if (buf_debug_prints && (count > 0)) {
 
285
                fprintf(stderr,
 
286
                        "Random read-ahead space %lu offset %lu pages %lu\n",
 
287
                        (ulong) space, (ulong) offset,
 
288
                        (ulong) count);
 
289
        }
 
290
#endif /* UNIV_DEBUG */
 
291
 
 
292
        ++srv_read_ahead_rnd;
 
293
        return(count);
 
294
}
 
295
 
 
296
/************************************************************************
 
297
High-level function which reads a page asynchronously from a file to the
 
298
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
 
299
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
 
300
released by the i/o-handler thread. Does a random read-ahead if it seems
 
301
sensible. */
 
302
 
 
303
ulint
 
304
buf_read_page(
 
305
/*==========*/
 
306
                        /* out: number of page read requests issued: this can
 
307
                        be > 1 if read-ahead occurred */
 
308
        ulint   space,  /* in: space id */
 
309
        ulint   offset) /* in: page number */
 
310
{
 
311
        ib_longlong     tablespace_version;
 
312
        ulint           count;
 
313
        ulint           count2;
 
314
        ulint           err;
 
315
 
 
316
        tablespace_version = fil_space_get_version(space);
 
317
 
 
318
        count = buf_read_ahead_random(space, offset);
 
319
 
 
320
        /* We do the i/o in the synchronous aio mode to save thread
 
321
        switches: hence TRUE */
 
322
 
 
323
        count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
 
324
                                   tablespace_version, offset);
 
325
        srv_buf_pool_reads+= count2;
 
326
        if (err == DB_TABLESPACE_DELETED) {
 
327
                ut_print_timestamp(stderr);
 
328
                fprintf(stderr,
 
329
                        "  InnoDB: Error: trying to access"
 
330
                        " tablespace %lu page no. %lu,\n"
 
331
                        "InnoDB: but the tablespace does not exist"
 
332
                        " or is just being dropped.\n",
 
333
                        (ulong) space, (ulong) offset);
 
334
        }
 
335
 
 
336
        /* Flush pages from the end of the LRU list if necessary */
 
337
        buf_flush_free_margin();
 
338
 
 
339
        return(count + count2);
 
340
}
 
341
 
 
342
/************************************************************************
 
343
Applies linear read-ahead if in the buf_pool the page is a border page of
 
344
a linear read-ahead area and all the pages in the area have been accessed.
 
345
Does not read any page if the read-ahead mechanism is not activated. Note
 
346
that the the algorithm looks at the 'natural' adjacent successor and
 
347
predecessor of the page, which on the leaf level of a B-tree are the next
 
348
and previous page in the chain of leaves. To know these, the page specified
 
349
in (space, offset) must already be present in the buf_pool. Thus, the
 
350
natural way to use this function is to call it when a page in the buf_pool
 
351
is accessed the first time, calling this function just after it has been
 
352
bufferfixed.
 
353
NOTE 1: as this function looks at the natural predecessor and successor
 
354
fields on the page, what happens, if these are not initialized to any
 
355
sensible value? No problem, before applying read-ahead we check that the
 
356
area to read is within the span of the space, if not, read-ahead is not
 
357
applied. An uninitialized value may result in a useless read operation, but
 
358
only very improbably.
 
359
NOTE 2: the calling thread may own latches on pages: to avoid deadlocks this
 
360
function must be written such that it cannot end up waiting for these
 
361
latches!
 
362
NOTE 3: the calling thread must want access to the page given: this rule is
 
363
set to prevent unintended read-aheads performed by ibuf routines, a situation
 
364
which could result in a deadlock if the OS does not support asynchronous io. */
 
365
 
 
366
ulint
 
367
buf_read_ahead_linear(
 
368
/*==================*/
 
369
                        /* out: number of page read requests issued */
 
370
        ulint   space,  /* in: space id */
 
371
        ulint   offset) /* in: page number of a page; NOTE: the current thread
 
372
                        must want access to this page (see NOTE 3 above) */
 
373
{
 
374
        ib_longlong     tablespace_version;
 
375
        buf_block_t*    block;
 
376
        buf_frame_t*    frame;
 
377
        buf_block_t*    pred_block      = NULL;
 
378
        ulint           pred_offset;
 
379
        ulint           succ_offset;
 
380
        ulint           count;
 
381
        int             asc_or_desc;
 
382
        ulint           new_offset;
 
383
        ulint           fail_count;
 
384
        ulint           ibuf_mode;
 
385
        ulint           low, high;
 
386
        ulint           err;
 
387
        ulint           i;
 
388
 
 
389
        if (srv_startup_is_before_trx_rollback_phase) {
 
390
                /* No read-ahead to avoid thread deadlocks */
 
391
                return(0);
 
392
        }
 
393
 
 
394
        if (ibuf_bitmap_page(offset) || trx_sys_hdr_page(space, offset)) {
 
395
 
 
396
                /* If it is an ibuf bitmap page or trx sys hdr, we do
 
397
                no read-ahead, as that could break the ibuf page access
 
398
                order */
 
399
 
 
400
                return(0);
 
401
        }
 
402
 
 
403
        low  = (offset / BUF_READ_AHEAD_LINEAR_AREA)
 
404
                * BUF_READ_AHEAD_LINEAR_AREA;
 
405
        high = (offset / BUF_READ_AHEAD_LINEAR_AREA + 1)
 
406
                * BUF_READ_AHEAD_LINEAR_AREA;
 
407
 
 
408
        if ((offset != low) && (offset != high - 1)) {
 
409
                /* This is not a border page of the area: return */
 
410
 
 
411
                return(0);
 
412
        }
 
413
 
 
414
        /* Remember the tablespace version before we ask te tablespace size
 
415
        below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
 
416
        do not try to read outside the bounds of the tablespace! */
 
417
 
 
418
        tablespace_version = fil_space_get_version(space);
 
419
 
 
420
        mutex_enter(&(buf_pool->mutex));
 
421
 
 
422
        if (high > fil_space_get_size(space)) {
 
423
                mutex_exit(&(buf_pool->mutex));
 
424
                /* The area is not whole, return */
 
425
 
 
426
                return(0);
 
427
        }
 
428
 
 
429
        if (buf_pool->n_pend_reads
 
430
            > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
 
431
                mutex_exit(&(buf_pool->mutex));
 
432
 
 
433
                return(0);
 
434
        }
 
435
 
 
436
        /* Check that almost all pages in the area have been accessed; if
 
437
        offset == low, the accesses must be in a descending order, otherwise,
 
438
        in an ascending order. */
 
439
 
 
440
        asc_or_desc = 1;
 
441
 
 
442
        if (offset == low) {
 
443
                asc_or_desc = -1;
 
444
        }
 
445
 
 
446
        fail_count = 0;
 
447
 
 
448
        for (i = low; i < high; i++) {
 
449
                block = buf_page_hash_get(space, i);
 
450
 
 
451
                if ((block == NULL) || !block->accessed) {
 
452
                        /* Not accessed */
 
453
                        fail_count++;
 
454
 
 
455
                } else if (pred_block
 
456
                           && (ut_ulint_cmp(block->LRU_position,
 
457
                                            pred_block->LRU_position)
 
458
                               != asc_or_desc)) {
 
459
                        /* Accesses not in the right order */
 
460
 
 
461
                        fail_count++;
 
462
                        pred_block = block;
 
463
                }
 
464
        }
 
465
 
 
466
        if (fail_count > BUF_READ_AHEAD_LINEAR_AREA
 
467
            - BUF_READ_AHEAD_LINEAR_THRESHOLD) {
 
468
                /* Too many failures: return */
 
469
 
 
470
                mutex_exit(&(buf_pool->mutex));
 
471
 
 
472
                return(0);
 
473
        }
 
474
 
 
475
        /* If we got this far, we know that enough pages in the area have
 
476
        been accessed in the right order: linear read-ahead can be sensible */
 
477
 
 
478
        block = buf_page_hash_get(space, offset);
 
479
 
 
480
        if (block == NULL) {
 
481
                mutex_exit(&(buf_pool->mutex));
 
482
 
 
483
                return(0);
 
484
        }
 
485
 
 
486
        frame = block->frame;
 
487
 
 
488
        /* Read the natural predecessor and successor page addresses from
 
489
        the page; NOTE that because the calling thread may have an x-latch
 
490
        on the page, we do not acquire an s-latch on the page, this is to
 
491
        prevent deadlocks. Even if we read values which are nonsense, the
 
492
        algorithm will work. */
 
493
 
 
494
        pred_offset = fil_page_get_prev(frame);
 
495
        succ_offset = fil_page_get_next(frame);
 
496
 
 
497
        mutex_exit(&(buf_pool->mutex));
 
498
 
 
499
        if ((offset == low) && (succ_offset == offset + 1)) {
 
500
 
 
501
                /* This is ok, we can continue */
 
502
                new_offset = pred_offset;
 
503
 
 
504
        } else if ((offset == high - 1) && (pred_offset == offset - 1)) {
 
505
 
 
506
                /* This is ok, we can continue */
 
507
                new_offset = succ_offset;
 
508
        } else {
 
509
                /* Successor or predecessor not in the right order */
 
510
 
 
511
                return(0);
 
512
        }
 
513
 
 
514
        low  = (new_offset / BUF_READ_AHEAD_LINEAR_AREA)
 
515
                * BUF_READ_AHEAD_LINEAR_AREA;
 
516
        high = (new_offset / BUF_READ_AHEAD_LINEAR_AREA + 1)
 
517
                * BUF_READ_AHEAD_LINEAR_AREA;
 
518
 
 
519
        if ((new_offset != low) && (new_offset != high - 1)) {
 
520
                /* This is not a border page of the area: return */
 
521
 
 
522
                return(0);
 
523
        }
 
524
 
 
525
        if (high > fil_space_get_size(space)) {
 
526
                /* The area is not whole, return */
 
527
 
 
528
                return(0);
 
529
        }
 
530
 
 
531
        /* If we got this far, read-ahead can be sensible: do it */
 
532
 
 
533
        if (ibuf_inside()) {
 
534
                ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
 
535
        } else {
 
536
                ibuf_mode = BUF_READ_ANY_PAGE;
 
537
        }
 
538
 
 
539
        count = 0;
 
540
 
 
541
        /* Since Windows XP seems to schedule the i/o handler thread
 
542
        very eagerly, and consequently it does not wait for the
 
543
        full read batch to be posted, we use special heuristics here */
 
544
 
 
545
        os_aio_simulated_put_read_threads_to_sleep();
 
546
 
 
547
        for (i = low; i < high; i++) {
 
548
                /* It is only sensible to do read-ahead in the non-sync
 
549
                aio mode: hence FALSE as the first parameter */
 
550
 
 
551
                if (!ibuf_bitmap_page(i)) {
 
552
                        count += buf_read_page_low(
 
553
                                &err, FALSE,
 
554
                                ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
 
555
                                space, tablespace_version, i);
 
556
                        if (err == DB_TABLESPACE_DELETED) {
 
557
                                ut_print_timestamp(stderr);
 
558
                                fprintf(stderr,
 
559
                                        "  InnoDB: Warning: in"
 
560
                                        " linear readahead trying to access\n"
 
561
                                        "InnoDB: tablespace %lu page %lu,\n"
 
562
                                        "InnoDB: but the tablespace does not"
 
563
                                        " exist or is just being dropped.\n",
 
564
                                        (ulong) space, (ulong) i);
 
565
                        }
 
566
                }
 
567
        }
 
568
 
 
569
        /* In simulated aio we wake the aio handler threads only after
 
570
        queuing all aio requests, in native aio the following call does
 
571
        nothing: */
 
572
 
 
573
        os_aio_simulated_wake_handler_threads();
 
574
 
 
575
        /* Flush pages from the end of the LRU list if necessary */
 
576
        buf_flush_free_margin();
 
577
 
 
578
#ifdef UNIV_DEBUG
 
579
        if (buf_debug_prints && (count > 0)) {
 
580
                fprintf(stderr,
 
581
                        "LINEAR read-ahead space %lu offset %lu pages %lu\n",
 
582
                        (ulong) space, (ulong) offset, (ulong) count);
 
583
        }
 
584
#endif /* UNIV_DEBUG */
 
585
 
 
586
        ++srv_read_ahead_seq;
 
587
        return(count);
 
588
}
 
589
 
 
590
/************************************************************************
 
591
Issues read requests for pages which the ibuf module wants to read in, in
 
592
order to contract the insert buffer tree. Technically, this function is like
 
593
a read-ahead function. */
 
594
 
 
595
void
 
596
buf_read_ibuf_merge_pages(
 
597
/*======================*/
 
598
        ibool   sync,           /* in: TRUE if the caller wants this function
 
599
                                to wait for the highest address page to get
 
600
                                read in, before this function returns */
 
601
        ulint*  space_ids,      /* in: array of space ids */
 
602
        ib_longlong* space_versions,/* in: the spaces must have this version
 
603
                                number (timestamp), otherwise we discard the
 
604
                                read; we use this to cancel reads if
 
605
                                DISCARD + IMPORT may have changed the
 
606
                                tablespace size */
 
607
        ulint*  page_nos,       /* in: array of page numbers to read, with the
 
608
                                highest page number the last in the array */
 
609
        ulint   n_stored)       /* in: number of page numbers in the array */
 
610
{
 
611
        ulint   err;
 
612
        ulint   i;
 
613
 
 
614
        ut_ad(!ibuf_inside());
 
615
#ifdef UNIV_IBUF_DEBUG
 
616
        ut_a(n_stored < UNIV_PAGE_SIZE);
 
617
#endif
 
618
        while (buf_pool->n_pend_reads
 
619
               > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
 
620
                os_thread_sleep(500000);
 
621
        }
 
622
 
 
623
        for (i = 0; i < n_stored; i++) {
 
624
                buf_read_page_low(&err,
 
625
                                  (i + 1 == n_stored) && sync,
 
626
                                  BUF_READ_ANY_PAGE,
 
627
                                  space_ids[i], space_versions[i],
 
628
                                  page_nos[i]);
 
629
 
 
630
                if (err == DB_TABLESPACE_DELETED) {
 
631
                        /* We have deleted or are deleting the single-table
 
632
                        tablespace: remove the entries for that page */
 
633
 
 
634
                        ibuf_merge_or_delete_for_page(NULL, space_ids[i],
 
635
                                                      page_nos[i], FALSE);
 
636
                }
 
637
        }
 
638
 
 
639
        os_aio_simulated_wake_handler_threads();
 
640
 
 
641
        /* Flush pages from the end of the LRU list if necessary */
 
642
        buf_flush_free_margin();
 
643
 
 
644
#ifdef UNIV_DEBUG
 
645
        if (buf_debug_prints) {
 
646
                fprintf(stderr,
 
647
                        "Ibuf merge read-ahead space %lu pages %lu\n",
 
648
                        (ulong) space_ids[0], (ulong) n_stored);
 
649
        }
 
650
#endif /* UNIV_DEBUG */
 
651
}
 
652
 
 
653
/************************************************************************
 
654
Issues read requests for pages which recovery wants to read in. */
 
655
 
 
656
void
 
657
buf_read_recv_pages(
 
658
/*================*/
 
659
        ibool   sync,           /* in: TRUE if the caller wants this function
 
660
                                to wait for the highest address page to get
 
661
                                read in, before this function returns */
 
662
        ulint   space,          /* in: space id */
 
663
        ulint*  page_nos,       /* in: array of page numbers to read, with the
 
664
                                highest page number the last in the array */
 
665
        ulint   n_stored)       /* in: number of page numbers in the array */
 
666
{
 
667
        ib_longlong     tablespace_version;
 
668
        ulint           count;
 
669
        ulint           err;
 
670
        ulint           i;
 
671
 
 
672
        tablespace_version = fil_space_get_version(space);
 
673
 
 
674
        for (i = 0; i < n_stored; i++) {
 
675
 
 
676
                count = 0;
 
677
 
 
678
                os_aio_print_debug = FALSE;
 
679
 
 
680
                while (buf_pool->n_pend_reads >= recv_n_pool_free_frames / 2) {
 
681
 
 
682
                        os_aio_simulated_wake_handler_threads();
 
683
                        os_thread_sleep(500000);
 
684
 
 
685
                        count++;
 
686
 
 
687
                        if (count > 100) {
 
688
                                fprintf(stderr,
 
689
                                        "InnoDB: Error: InnoDB has waited for"
 
690
                                        " 50 seconds for pending\n"
 
691
                                        "InnoDB: reads to the buffer pool to"
 
692
                                        " be finished.\n"
 
693
                                        "InnoDB: Number of pending reads %lu,"
 
694
                                        " pending pread calls %lu\n",
 
695
                                        (ulong) buf_pool->n_pend_reads,
 
696
                                        (ulong)os_file_n_pending_preads);
 
697
 
 
698
                                os_aio_print_debug = TRUE;
 
699
                        }
 
700
                }
 
701
 
 
702
                os_aio_print_debug = FALSE;
 
703
 
 
704
                if ((i + 1 == n_stored) && sync) {
 
705
                        buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE,
 
706
                                          space, tablespace_version,
 
707
                                          page_nos[i]);
 
708
                } else {
 
709
                        buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
 
710
                                          | OS_AIO_SIMULATED_WAKE_LATER,
 
711
                                          space, tablespace_version,
 
712
                                          page_nos[i]);
 
713
                }
 
714
        }
 
715
 
 
716
        os_aio_simulated_wake_handler_threads();
 
717
 
 
718
        /* Flush pages from the end of the LRU list if necessary */
 
719
        buf_flush_free_margin();
 
720
 
 
721
#ifdef UNIV_DEBUG
 
722
        if (buf_debug_prints) {
 
723
                fprintf(stderr,
 
724
                        "Recovery applies read-ahead pages %lu\n",
 
725
                        (ulong) n_stored);
 
726
        }
 
727
#endif /* UNIV_DEBUG */
 
728
}