~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

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

Show diffs side-by-side

added added

removed removed

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