~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Eric Day
  • Date: 2009-10-31 21:53:33 UTC
  • mfrom: (1200 staging)
  • mto: This revision was merged to the branch mainline in revision 1202.
  • Revision ID: eday@oddments.org-20091031215333-j94bjoanwmi68p6f
Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
*****************************************************************************/
18
18
 
19
 
/******************************************************
 
19
/**************************************************//**
 
20
@file buf/buf0rea.c
20
21
The database buffer read
21
22
 
22
23
Created 11/5/1995 Heikki Tuuri
37
38
#include "srv0start.h"
38
39
#include "srv0srv.h"
39
40
 
40
 
/* The size in blocks of the area where the random read-ahead algorithm counts
 
41
/** The size in blocks of the area where the random read-ahead algorithm counts
41
42
the accessed pages when deciding whether to read-ahead */
42
43
#define BUF_READ_AHEAD_RANDOM_AREA      BUF_READ_AHEAD_AREA
43
44
 
44
 
/* There must be at least this many pages in buf_pool in the area to start
 
45
/** There must be at least this many pages in buf_pool in the area to start
45
46
a random read-ahead */
46
 
#define BUF_READ_AHEAD_RANDOM_THRESHOLD (5 + buf_read_ahead_random_area / 8)
 
47
#define BUF_READ_AHEAD_RANDOM_THRESHOLD (1 + BUF_READ_AHEAD_RANDOM_AREA / 2)
47
48
 
48
 
/* The linear read-ahead area size */
 
49
/** The linear read-ahead area size */
49
50
#define BUF_READ_AHEAD_LINEAR_AREA      BUF_READ_AHEAD_AREA
50
51
 
51
 
/* The linear read-ahead threshold */
52
 
#define LINEAR_AREA_THRESHOLD_COEF      5 / 8
53
 
 
54
 
/* If there are buf_pool->curr_size per the number below pending reads, then
 
52
/** If there are buf_pool->curr_size per the number below pending reads, then
55
53
read-ahead is not done: this is to prevent flooding the buffer pool with
56
54
i/o-fixed buffer blocks */
57
55
#define BUF_READ_AHEAD_PEND_LIMIT       2
58
56
 
59
 
/************************************************************************
 
57
/********************************************************************//**
60
58
Low-level function which reads a page asynchronously from a file to the
61
59
buffer buf_pool if it is not already there, in which case does nothing.
62
60
Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
63
 
flag is cleared and the x-lock released by an i/o-handler thread. */
 
61
flag is cleared and the x-lock released by an i/o-handler thread.
 
62
@return 1 if a read request was queued, 0 if the page already resided
 
63
in buf_pool, or if the page is in the doublewrite buffer blocks in
 
64
which case it is never read into the pool, or if the tablespace does
 
65
not exist or is being dropped */
64
66
static
65
67
ulint
66
68
buf_read_page_low(
67
69
/*==============*/
68
 
                        /* out: 1 if a read request was queued, 0 if the page
69
 
                        already resided in buf_pool, or if the page is in
70
 
                        the doublewrite buffer blocks in which case it is never
71
 
                        read into the pool, or if the tablespace does not
72
 
                        exist or is being dropped */
73
 
        ulint*  err,    /* out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
 
70
        ulint*  err,    /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
74
71
                        trying to read from a non-existent tablespace, or a
75
72
                        tablespace which is just now being dropped */
76
 
        ibool   sync,   /* in: TRUE if synchronous aio is desired */
77
 
        ulint   mode,   /* in: BUF_READ_IBUF_PAGES_ONLY, ...,
 
73
        ibool   sync,   /*!< in: TRUE if synchronous aio is desired */
 
74
        ulint   mode,   /*!< in: BUF_READ_IBUF_PAGES_ONLY, ...,
78
75
                        ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
79
76
                        at read-ahead functions) */
80
 
        ulint   space,  /* in: space id */
81
 
        ulint   zip_size,/* in: compressed page size, or 0 */
82
 
        ibool   unzip,  /* in: TRUE=request uncompressed page */
83
 
        ib_int64_t tablespace_version, /* in: if the space memory object has
 
77
        ulint   space,  /*!< in: space id */
 
78
        ulint   zip_size,/*!< in: compressed page size, or 0 */
 
79
        ibool   unzip,  /*!< in: TRUE=request uncompressed page */
 
80
        ib_int64_t tablespace_version, /*!< in: if the space memory object has
84
81
                        this timestamp different from what we are giving here,
85
82
                        treat the tablespace as dropped; this is a timestamp we
86
83
                        use to stop dangling page reads from a tablespace
87
84
                        which we have DISCARDed + IMPORTed back */
88
 
        ulint   offset) /* in: page number */
 
85
        ulint   offset) /*!< in: page number */
89
86
{
90
87
        buf_page_t*     bpage;
91
88
        ulint           wake_later;
167
164
        return(1);
168
165
}
169
166
 
170
 
/************************************************************************
 
167
/********************************************************************//**
171
168
Applies a random read-ahead in buf_pool if there are at least a threshold
172
169
value of accessed pages from the random read-ahead area. Does not read any
173
170
page, not even the one at the position (space, offset), if the read-ahead
176
173
end up waiting for these latches! NOTE 2: the calling thread must want
177
174
access to the page given: this rule is set to prevent unintended read-aheads
178
175
performed by ibuf routines, a situation which could result in a deadlock if
179
 
the OS does not support asynchronous i/o. */
 
176
the OS does not support asynchronous i/o.
 
177
@return number of page read requests issued; NOTE that if we read ibuf
 
178
pages, it may happen that the page at the given page number does not
 
179
get read even if we return a positive value! */
180
180
static
181
181
ulint
182
182
buf_read_ahead_random(
183
183
/*==================*/
184
 
                        /* out: number of page read requests issued; NOTE
185
 
                        that if we read ibuf pages, it may happen that
186
 
                        the page at the given page number does not get
187
 
                        read even if we return a value > 0! */
188
 
        ulint   space,  /* in: space id */
189
 
        ulint   zip_size,/* in: compressed page size in bytes, or 0 */
190
 
        ulint   offset) /* in: page number of a page which the current thread
 
184
        ulint   space,  /*!< in: space id */
 
185
        ulint   zip_size,/*!< in: compressed page size in bytes, or 0 */
 
186
        ulint   offset) /*!< in: page number of a page which the current thread
191
187
                        wants to access */
192
188
{
193
 
        ib_int64_t      tablespace_version;
194
 
        ulint           recent_blocks   = 0;
195
 
        ulint           count;
196
 
        ulint           LRU_recent_limit;
197
 
        ulint           ibuf_mode;
198
 
        ulint           low, high;
199
 
        ulint           err;
200
 
        ulint           i;
201
 
        ulint           buf_read_ahead_random_area;
202
 
 
203
 
        if (srv_startup_is_before_trx_rollback_phase) {
204
 
                /* No read-ahead to avoid thread deadlocks */
205
 
                return(0);
206
 
        }
207
 
 
208
 
        if (ibuf_bitmap_page(zip_size, offset)
209
 
            || trx_sys_hdr_page(space, offset)) {
210
 
 
211
 
                /* If it is an ibuf bitmap page or trx sys hdr, we do
212
 
                no read-ahead, as that could break the ibuf page access
213
 
                order */
214
 
 
215
 
                return(0);
216
 
        }
217
 
 
218
 
        /* Remember the tablespace version before we ask te tablespace size
219
 
        below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
220
 
        do not try to read outside the bounds of the tablespace! */
221
 
 
222
 
        tablespace_version = fil_space_get_version(space);
223
 
 
224
 
        buf_read_ahead_random_area = BUF_READ_AHEAD_RANDOM_AREA;
225
 
 
226
 
        low  = (offset / buf_read_ahead_random_area)
227
 
                * buf_read_ahead_random_area;
228
 
        high = (offset / buf_read_ahead_random_area + 1)
229
 
                * buf_read_ahead_random_area;
230
 
        if (high > fil_space_get_size(space)) {
231
 
 
232
 
                high = fil_space_get_size(space);
233
 
        }
234
 
 
235
 
        /* Get the minimum LRU_position field value for an initial segment
236
 
        of the LRU list, to determine which blocks have recently been added
237
 
        to the start of the list. */
238
 
 
239
 
        LRU_recent_limit = buf_LRU_get_recent_limit();
240
 
 
241
 
        buf_pool_mutex_enter();
242
 
 
243
 
        if (buf_pool->n_pend_reads
244
 
            > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
245
 
                buf_pool_mutex_exit();
246
 
 
247
 
                return(0);
248
 
        }
249
 
 
250
 
        /* Count how many blocks in the area have been recently accessed,
251
 
        that is, reside near the start of the LRU list. */
252
 
 
253
 
        for (i = low; i < high; i++) {
254
 
                const buf_page_t*       bpage = buf_page_hash_get(space, i);
255
 
 
256
 
                if (bpage
257
 
                    && buf_page_is_accessed(bpage)
258
 
                    && (buf_page_get_LRU_position(bpage) > LRU_recent_limit)) {
259
 
 
260
 
                        recent_blocks++;
261
 
 
262
 
                        if (recent_blocks >= BUF_READ_AHEAD_RANDOM_THRESHOLD) {
263
 
 
264
 
                                buf_pool_mutex_exit();
265
 
                                goto read_ahead;
266
 
                        }
267
 
                }
268
 
        }
269
 
 
270
 
        buf_pool_mutex_exit();
271
 
        /* Do nothing */
 
189
        (void)space;
 
190
        (void)zip_size;
 
191
        (void)offset;
 
192
        /* We have currently disabled random readahead */
272
193
        return(0);
273
194
 
274
 
read_ahead:
275
 
        /* Read all the suitable blocks within the area */
276
 
 
277
 
        if (ibuf_inside()) {
278
 
                ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
279
 
        } else {
280
 
                ibuf_mode = BUF_READ_ANY_PAGE;
281
 
        }
282
 
 
283
 
        count = 0;
284
 
 
285
 
        for (i = low; i < high; i++) {
286
 
                /* It is only sensible to do read-ahead in the non-sync aio
287
 
                mode: hence FALSE as the first parameter */
288
 
 
289
 
                if (!ibuf_bitmap_page(zip_size, i)) {
290
 
                        count += buf_read_page_low(
291
 
                                &err, FALSE,
292
 
                                ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
293
 
                                space, zip_size, FALSE,
294
 
                                tablespace_version, i);
295
 
                        if (err == DB_TABLESPACE_DELETED) {
296
 
                                ut_print_timestamp(stderr);
297
 
                                fprintf(stderr,
298
 
                                        "  InnoDB: Warning: in random"
299
 
                                        " readahead trying to access\n"
300
 
                                        "InnoDB: tablespace %lu page %lu,\n"
301
 
                                        "InnoDB: but the tablespace does not"
302
 
                                        " exist or is just being dropped.\n",
303
 
                                        (ulong) space, (ulong) i);
304
 
                        }
305
 
                }
306
 
        }
307
 
 
308
 
        /* In simulated aio we wake the aio handler threads only after
309
 
        queuing all aio requests, in native aio the following call does
310
 
        nothing: */
311
 
 
312
 
        os_aio_simulated_wake_handler_threads();
313
 
 
314
 
#ifdef UNIV_DEBUG
315
 
        if (buf_debug_prints && (count > 0)) {
316
 
                fprintf(stderr,
317
 
                        "Random read-ahead space %lu offset %lu pages %lu\n",
318
 
                        (ulong) space, (ulong) offset,
319
 
                        (ulong) count);
320
 
        }
321
 
#endif /* UNIV_DEBUG */
322
 
 
323
 
        ++srv_read_ahead_rnd;
324
 
        return(count);
325
195
}
326
196
 
327
 
/************************************************************************
 
197
/********************************************************************//**
328
198
High-level function which reads a page asynchronously from a file to the
329
199
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
330
200
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
331
201
released by the i/o-handler thread. Does a random read-ahead if it seems
332
 
sensible. */
 
202
sensible.
 
203
@return number of page read requests issued: this can be greater than
 
204
1 if read-ahead occurred */
333
205
UNIV_INTERN
334
206
ulint
335
207
buf_read_page(
336
208
/*==========*/
337
 
                        /* out: number of page read requests issued: this can
338
 
                        be > 1 if read-ahead occurred */
339
 
        ulint   space,  /* in: space id */
340
 
        ulint   zip_size,/* in: compressed page size in bytes, or 0 */
341
 
        ulint   offset) /* in: page number */
 
209
        ulint   space,  /*!< in: space id */
 
210
        ulint   zip_size,/*!< in: compressed page size in bytes, or 0 */
 
211
        ulint   offset) /*!< in: page number */
342
212
{
343
213
        ib_int64_t      tablespace_version;
344
214
        ulint           count;
375
245
        return(count + count2);
376
246
}
377
247
 
378
 
/************************************************************************
 
248
/********************************************************************//**
379
249
Applies linear read-ahead if in the buf_pool the page is a border page of
380
250
a linear read-ahead area and all the pages in the area have been accessed.
381
251
Does not read any page if the read-ahead mechanism is not activated. Note
397
267
latches!
398
268
NOTE 3: the calling thread must want access to the page given: this rule is
399
269
set to prevent unintended read-aheads performed by ibuf routines, a situation
400
 
which could result in a deadlock if the OS does not support asynchronous io. */
 
270
which could result in a deadlock if the OS does not support asynchronous io.
 
271
@return number of page read requests issued */
401
272
UNIV_INTERN
402
273
ulint
403
274
buf_read_ahead_linear(
404
275
/*==================*/
405
 
                        /* out: number of page read requests issued */
406
 
        ulint   space,  /* in: space id */
407
 
        ulint   zip_size,/* in: compressed page size in bytes, or 0 */
408
 
        ulint   offset) /* in: page number of a page; NOTE: the current thread
 
276
        ulint   space,  /*!< in: space id */
 
277
        ulint   zip_size,/*!< in: compressed page size in bytes, or 0 */
 
278
        ulint   offset) /*!< in: page number of a page; NOTE: the current thread
409
279
                        must want access to this page (see NOTE 3 above) */
410
280
{
411
281
        ib_int64_t      tablespace_version;
424
294
        ulint           i;
425
295
        const ulint     buf_read_ahead_linear_area
426
296
                = BUF_READ_AHEAD_LINEAR_AREA;
 
297
        ulint           threshold;
427
298
 
428
299
        if (UNIV_UNLIKELY(srv_startup_is_before_trx_rollback_phase)) {
429
300
                /* No read-ahead to avoid thread deadlocks */
483
354
                asc_or_desc = -1;
484
355
        }
485
356
 
 
357
        /* How many out of order accessed pages can we ignore
 
358
        when working out the access pattern for linear readahead */
 
359
        threshold = ut_min((64 - srv_read_ahead_threshold),
 
360
                           BUF_READ_AHEAD_AREA);
 
361
 
486
362
        fail_count = 0;
487
363
 
488
364
        for (i = low; i < high; i++) {
492
368
                        /* Not accessed */
493
369
                        fail_count++;
494
370
 
495
 
                } else if (pred_bpage
496
 
                           && (ut_ulint_cmp(
 
371
                } else if (pred_bpage) {
 
372
                        int res = (ut_ulint_cmp(
497
373
                                       buf_page_get_LRU_position(bpage),
498
 
                                       buf_page_get_LRU_position(pred_bpage))
499
 
                               != asc_or_desc)) {
 
374
                                       buf_page_get_LRU_position(pred_bpage)));
500
375
                        /* Accesses not in the right order */
501
 
 
502
 
                        fail_count++;
 
376
                        if (res != 0 && res != asc_or_desc) {
 
377
                                fail_count++;
 
378
                        }
 
379
                }
 
380
 
 
381
                if (fail_count > threshold) {
 
382
                        /* Too many failures: return */
 
383
                        buf_pool_mutex_exit();
 
384
                        return(0);
 
385
                }
 
386
 
 
387
                if (bpage && buf_page_is_accessed(bpage)) {
503
388
                        pred_bpage = bpage;
504
389
                }
505
390
        }
506
391
 
507
 
        if (fail_count > buf_read_ahead_linear_area
508
 
            * LINEAR_AREA_THRESHOLD_COEF) {
509
 
                /* Too many failures: return */
510
 
 
511
 
                buf_pool_mutex_exit();
512
 
 
513
 
                return(0);
514
 
        }
515
 
 
516
392
        /* If we got this far, we know that enough pages in the area have
517
393
        been accessed in the right order: linear read-ahead can be sensible */
518
394
 
642
518
        return(count);
643
519
}
644
520
 
645
 
/************************************************************************
 
521
/********************************************************************//**
646
522
Issues read requests for pages which the ibuf module wants to read in, in
647
523
order to contract the insert buffer tree. Technically, this function is like
648
524
a read-ahead function. */
650
526
void
651
527
buf_read_ibuf_merge_pages(
652
528
/*======================*/
653
 
        ibool           sync,           /* in: TRUE if the caller
 
529
        ibool           sync,           /*!< in: TRUE if the caller
654
530
                                        wants this function to wait
655
531
                                        for the highest address page
656
532
                                        to get read in, before this
657
533
                                        function returns */
658
 
        const ulint*    space_ids,      /* in: array of space ids */
659
 
        const ib_int64_t* space_versions,/* in: the spaces must have
 
534
        const ulint*    space_ids,      /*!< in: array of space ids */
 
535
        const ib_int64_t* space_versions,/*!< in: the spaces must have
660
536
                                        this version number
661
537
                                        (timestamp), otherwise we
662
538
                                        discard the read; we use this
663
539
                                        to cancel reads if DISCARD +
664
540
                                        IMPORT may have changed the
665
541
                                        tablespace size */
666
 
        const ulint*    page_nos,       /* in: array of page numbers
 
542
        const ulint*    page_nos,       /*!< in: array of page numbers
667
543
                                        to read, with the highest page
668
544
                                        number the last in the
669
545
                                        array */
670
 
        ulint           n_stored)       /* in: number of elements
 
546
        ulint           n_stored)       /*!< in: number of elements
671
547
                                        in the arrays */
672
548
{
673
549
        ulint   i;
720
596
#endif /* UNIV_DEBUG */
721
597
}
722
598
 
723
 
/************************************************************************
 
599
/********************************************************************//**
724
600
Issues read requests for pages which recovery wants to read in. */
725
601
UNIV_INTERN
726
602
void
727
603
buf_read_recv_pages(
728
604
/*================*/
729
 
        ibool           sync,           /* in: TRUE if the caller
 
605
        ibool           sync,           /*!< in: TRUE if the caller
730
606
                                        wants this function to wait
731
607
                                        for the highest address page
732
608
                                        to get read in, before this
733
609
                                        function returns */
734
 
        ulint           space,          /* in: space id */
735
 
        ulint           zip_size,       /* in: compressed page size in
 
610
        ulint           space,          /*!< in: space id */
 
611
        ulint           zip_size,       /*!< in: compressed page size in
736
612
                                        bytes, or 0 */
737
 
        const ulint*    page_nos,       /* in: array of page numbers
 
613
        const ulint*    page_nos,       /*!< in: array of page numbers
738
614
                                        to read, with the highest page
739
615
                                        number the last in the
740
616
                                        array */
741
 
        ulint           n_stored)       /* in: number of page numbers
 
617
        ulint           n_stored)       /*!< in: number of page numbers
742
618
                                        in the array */
743
619
{
744
620
        ib_int64_t      tablespace_version;
747
623
        ulint           i;
748
624
 
749
625
        zip_size = fil_space_get_zip_size(space);
 
626
 
 
627
        if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
 
628
                /* It is a single table tablespace and the .ibd file is
 
629
                missing: do nothing */
 
630
 
 
631
                return;
 
632
        }
 
633
 
750
634
        tablespace_version = fil_space_get_version(space);
751
635
 
752
636
        for (i = 0; i < n_stored; i++) {