~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Renamed more stuff to drizzle.

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