~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2008-11-16 20:15:33 UTC
  • mto: (584.1.9 devel)
  • mto: This revision was merged to the branch mainline in revision 589.
  • Revision ID: monty@inaugust.com-20081116201533-d0f19s1bk1h95iyw
Removed a big bank of includes from item.h.

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
}