~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/include/buf0buf.ic

  • Committer: Brian Aker
  • Date: 2010-08-12 17:21:13 UTC
  • mfrom: (1689.5.5 remove_pthread_calls)
  • Revision ID: brian@tangent.org-20100812172113-i0ox868kcbzjim2h
Merge in removal of pthread dead wrappers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
4
 
Copyright (c) 2008, Google Inc.
5
 
 
6
 
Portions of this file contain modifications contributed and copyrighted by
7
 
Google, Inc. Those modifications are gratefully acknowledged and are described
8
 
briefly in the InnoDB documentation. The contributions by Google are
9
 
incorporated with their permission, and subject to the conditions contained in
10
 
the file COPYING.Google.
11
 
 
12
 
This program is free software; you can redistribute it and/or modify it under
13
 
the terms of the GNU General Public License as published by the Free Software
14
 
Foundation; version 2 of the License.
15
 
 
16
 
This program is distributed in the hope that it will be useful, but WITHOUT
17
 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
 
 
20
 
You should have received a copy of the GNU General Public License along with
21
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22
 
St, Fifth Floor, Boston, MA 02110-1301 USA
23
 
 
24
 
*****************************************************************************/
25
 
 
26
 
/**************************************************//**
27
 
@file include/buf0buf.ic
28
 
The database buffer buf_pool
29
 
 
30
 
Created 11/5/1995 Heikki Tuuri
31
 
*******************************************************/
32
 
 
33
 
#include "mtr0mtr.h"
34
 
#include "buf0flu.h"
35
 
#include "buf0lru.h"
36
 
#include "buf0rea.h"
37
 
#include "srv0srv.h"
38
 
 
39
 
/*********************************************************************//**
40
 
Gets the current size of buffer buf_pool in bytes.
41
 
@return size in bytes */
42
 
UNIV_INLINE
43
 
ulint
44
 
buf_pool_get_curr_size(void)
45
 
/*========================*/
46
 
{
47
 
        return(srv_buf_pool_curr_size);
48
 
}
49
 
 
50
 
/*********************************************************************//**
51
 
Gets the current size of buffer buf_pool in pages.
52
 
@return size in pages*/
53
 
UNIV_INLINE
54
 
ulint
55
 
buf_pool_get_n_pages(void)
56
 
/*======================*/
57
 
{
58
 
        return(buf_pool_get_curr_size() / UNIV_PAGE_SIZE);
59
 
}
60
 
 
61
 
/********************************************************************//**
62
 
Reads the freed_page_clock of a buffer block.
63
 
@return freed_page_clock */
64
 
UNIV_INLINE
65
 
ulint
66
 
buf_page_get_freed_page_clock(
67
 
/*==========================*/
68
 
        const buf_page_t*       bpage)  /*!< in: block */
69
 
{
70
 
        /* This is sometimes read without holding buf_pool->mutex. */
71
 
        return(bpage->freed_page_clock);
72
 
}
73
 
 
74
 
/********************************************************************//**
75
 
Reads the freed_page_clock of a buffer block.
76
 
@return freed_page_clock */
77
 
UNIV_INLINE
78
 
ulint
79
 
buf_block_get_freed_page_clock(
80
 
/*===========================*/
81
 
        const buf_block_t*      block)  /*!< in: block */
82
 
{
83
 
        return(buf_page_get_freed_page_clock(&block->page));
84
 
}
85
 
 
86
 
/********************************************************************//**
87
 
Recommends a move of a block to the start of the LRU list if there is danger
88
 
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
89
 
mutex.
90
 
@return TRUE if should be made younger */
91
 
UNIV_INLINE
92
 
ibool
93
 
buf_page_peek_if_too_old(
94
 
/*=====================*/
95
 
        const buf_page_t*       bpage)  /*!< in: block to make younger */
96
 
{
97
 
        buf_pool_t*             buf_pool = buf_pool_from_bpage(bpage);
98
 
 
99
 
        if (UNIV_UNLIKELY(buf_pool->freed_page_clock == 0)) {
100
 
                /* If eviction has not started yet, do not update the
101
 
                statistics or move blocks in the LRU list.  This is
102
 
                either the warm-up phase or an in-memory workload. */
103
 
                return(FALSE);
104
 
        } else if (buf_LRU_old_threshold_ms && bpage->old) {
105
 
                unsigned        access_time = buf_page_is_accessed(bpage);
106
 
 
107
 
                if (access_time > 0
108
 
                    && ((ib_uint32_t) (ut_time_ms() - access_time))
109
 
                    >= buf_LRU_old_threshold_ms) {
110
 
                        return(TRUE);
111
 
                }
112
 
 
113
 
                buf_pool->stat.n_pages_not_made_young++;
114
 
                return(FALSE);
115
 
        } else {
116
 
                /* FIXME: bpage->freed_page_clock is 31 bits */
117
 
                return((buf_pool->freed_page_clock & ((1UL << 31) - 1))
118
 
                       > ((ulint) bpage->freed_page_clock
119
 
                          + (buf_pool->curr_size
120
 
                             * (BUF_LRU_OLD_RATIO_DIV - buf_pool->LRU_old_ratio)
121
 
                             / (BUF_LRU_OLD_RATIO_DIV * 4))));
122
 
        }
123
 
}
124
 
 
125
 
/*********************************************************************//**
126
 
Gets the state of a block.
127
 
@return state */
128
 
UNIV_INLINE
129
 
enum buf_page_state
130
 
buf_page_get_state(
131
 
/*===============*/
132
 
        const buf_page_t*       bpage)  /*!< in: pointer to the control block */
133
 
{
134
 
        enum buf_page_state     state = (enum buf_page_state) bpage->state;
135
 
 
136
 
#ifdef UNIV_DEBUG
137
 
        switch (state) {
138
 
        case BUF_BLOCK_ZIP_FREE:
139
 
        case BUF_BLOCK_ZIP_PAGE:
140
 
        case BUF_BLOCK_ZIP_DIRTY:
141
 
        case BUF_BLOCK_NOT_USED:
142
 
        case BUF_BLOCK_READY_FOR_USE:
143
 
        case BUF_BLOCK_FILE_PAGE:
144
 
        case BUF_BLOCK_MEMORY:
145
 
        case BUF_BLOCK_REMOVE_HASH:
146
 
                break;
147
 
        default:
148
 
                ut_error;
149
 
        }
150
 
#endif /* UNIV_DEBUG */
151
 
 
152
 
        return(state);
153
 
}
154
 
/*********************************************************************//**
155
 
Gets the state of a block.
156
 
@return state */
157
 
UNIV_INLINE
158
 
enum buf_page_state
159
 
buf_block_get_state(
160
 
/*================*/
161
 
        const buf_block_t*      block)  /*!< in: pointer to the control block */
162
 
{
163
 
        return(buf_page_get_state(&block->page));
164
 
}
165
 
/*********************************************************************//**
166
 
Sets the state of a block. */
167
 
UNIV_INLINE
168
 
void
169
 
buf_page_set_state(
170
 
/*===============*/
171
 
        buf_page_t*             bpage,  /*!< in/out: pointer to control block */
172
 
        enum buf_page_state     state)  /*!< in: state */
173
 
{
174
 
#ifdef UNIV_DEBUG
175
 
        enum buf_page_state     old_state       = buf_page_get_state(bpage);
176
 
 
177
 
        switch (old_state) {
178
 
        case BUF_BLOCK_ZIP_FREE:
179
 
                ut_error;
180
 
                break;
181
 
        case BUF_BLOCK_ZIP_PAGE:
182
 
                ut_a(state == BUF_BLOCK_ZIP_DIRTY);
183
 
                break;
184
 
        case BUF_BLOCK_ZIP_DIRTY:
185
 
                ut_a(state == BUF_BLOCK_ZIP_PAGE);
186
 
                break;
187
 
        case BUF_BLOCK_NOT_USED:
188
 
                ut_a(state == BUF_BLOCK_READY_FOR_USE);
189
 
                break;
190
 
        case BUF_BLOCK_READY_FOR_USE:
191
 
                ut_a(state == BUF_BLOCK_MEMORY
192
 
                     || state == BUF_BLOCK_FILE_PAGE
193
 
                     || state == BUF_BLOCK_NOT_USED);
194
 
                break;
195
 
        case BUF_BLOCK_MEMORY:
196
 
                ut_a(state == BUF_BLOCK_NOT_USED);
197
 
                break;
198
 
        case BUF_BLOCK_FILE_PAGE:
199
 
                ut_a(state == BUF_BLOCK_NOT_USED
200
 
                     || state == BUF_BLOCK_REMOVE_HASH);
201
 
                break;
202
 
        case BUF_BLOCK_REMOVE_HASH:
203
 
                ut_a(state == BUF_BLOCK_MEMORY);
204
 
                break;
205
 
        }
206
 
#endif /* UNIV_DEBUG */
207
 
        bpage->state = state;
208
 
        ut_ad(buf_page_get_state(bpage) == state);
209
 
}
210
 
 
211
 
/*********************************************************************//**
212
 
Sets the state of a block. */
213
 
UNIV_INLINE
214
 
void
215
 
buf_block_set_state(
216
 
/*================*/
217
 
        buf_block_t*            block,  /*!< in/out: pointer to control block */
218
 
        enum buf_page_state     state)  /*!< in: state */
219
 
{
220
 
        buf_page_set_state(&block->page, state);
221
 
}
222
 
 
223
 
/*********************************************************************//**
224
 
Determines if a block is mapped to a tablespace.
225
 
@return TRUE if mapped */
226
 
UNIV_INLINE
227
 
ibool
228
 
buf_page_in_file(
229
 
/*=============*/
230
 
        const buf_page_t*       bpage)  /*!< in: pointer to control block */
231
 
{
232
 
        switch (buf_page_get_state(bpage)) {
233
 
        case BUF_BLOCK_ZIP_FREE:
234
 
                /* This is a free page in buf_pool->zip_free[].
235
 
                Such pages should only be accessed by the buddy allocator. */
236
 
                ut_error;
237
 
                break;
238
 
        case BUF_BLOCK_ZIP_PAGE:
239
 
        case BUF_BLOCK_ZIP_DIRTY:
240
 
        case BUF_BLOCK_FILE_PAGE:
241
 
                return(TRUE);
242
 
        case BUF_BLOCK_NOT_USED:
243
 
        case BUF_BLOCK_READY_FOR_USE:
244
 
        case BUF_BLOCK_MEMORY:
245
 
        case BUF_BLOCK_REMOVE_HASH:
246
 
                break;
247
 
        }
248
 
 
249
 
        return(FALSE);
250
 
}
251
 
 
252
 
#ifndef UNIV_HOTBACKUP
253
 
/*********************************************************************//**
254
 
Determines if a block should be on unzip_LRU list.
255
 
@return TRUE if block belongs to unzip_LRU */
256
 
UNIV_INLINE
257
 
ibool
258
 
buf_page_belongs_to_unzip_LRU(
259
 
/*==========================*/
260
 
        const buf_page_t*       bpage)  /*!< in: pointer to control block */
261
 
{
262
 
        ut_ad(buf_page_in_file(bpage));
263
 
 
264
 
        return(bpage->zip.data
265
 
               && buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
266
 
}
267
 
 
268
 
/*********************************************************************//**
269
 
Gets the mutex of a block.
270
 
@return pointer to mutex protecting bpage */
271
 
UNIV_INLINE
272
 
mutex_t*
273
 
buf_page_get_mutex(
274
 
/*===============*/
275
 
        const buf_page_t*       bpage)  /*!< in: pointer to control block */
276
 
{
277
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
278
 
 
279
 
        switch (buf_page_get_state(bpage)) {
280
 
        case BUF_BLOCK_ZIP_FREE:
281
 
                ut_error;
282
 
                return(NULL);
283
 
        case BUF_BLOCK_ZIP_PAGE:
284
 
        case BUF_BLOCK_ZIP_DIRTY:
285
 
                return(&buf_pool->zip_mutex);
286
 
        default:
287
 
                return(&((buf_block_t*) bpage)->mutex);
288
 
        }
289
 
}
290
 
 
291
 
/*********************************************************************//**
292
 
Get the flush type of a page.
293
 
@return flush type */
294
 
UNIV_INLINE
295
 
enum buf_flush
296
 
buf_page_get_flush_type(
297
 
/*====================*/
298
 
        const buf_page_t*       bpage)  /*!< in: buffer page */
299
 
{
300
 
        enum buf_flush  flush_type = (enum buf_flush) bpage->flush_type;
301
 
 
302
 
#ifdef UNIV_DEBUG
303
 
        switch (flush_type) {
304
 
        case BUF_FLUSH_LRU:
305
 
        case BUF_FLUSH_SINGLE_PAGE:
306
 
        case BUF_FLUSH_LIST:
307
 
                return(flush_type);
308
 
        case BUF_FLUSH_N_TYPES:
309
 
                break;
310
 
        }
311
 
        ut_error;
312
 
#endif /* UNIV_DEBUG */
313
 
        return(flush_type);
314
 
}
315
 
/*********************************************************************//**
316
 
Set the flush type of a page. */
317
 
UNIV_INLINE
318
 
void
319
 
buf_page_set_flush_type(
320
 
/*====================*/
321
 
        buf_page_t*     bpage,          /*!< in: buffer page */
322
 
        enum buf_flush  flush_type)     /*!< in: flush type */
323
 
{
324
 
        bpage->flush_type = flush_type;
325
 
        ut_ad(buf_page_get_flush_type(bpage) == flush_type);
326
 
}
327
 
 
328
 
/*********************************************************************//**
329
 
Map a block to a file page. */
330
 
UNIV_INLINE
331
 
void
332
 
buf_block_set_file_page(
333
 
/*====================*/
334
 
        buf_block_t*            block,  /*!< in/out: pointer to control block */
335
 
        ulint                   space,  /*!< in: tablespace id */
336
 
        ulint                   page_no)/*!< in: page number */
337
 
{
338
 
        buf_block_set_state(block, BUF_BLOCK_FILE_PAGE);
339
 
        block->page.space = space;
340
 
        block->page.offset = page_no;
341
 
}
342
 
 
343
 
/*********************************************************************//**
344
 
Gets the io_fix state of a block.
345
 
@return io_fix state */
346
 
UNIV_INLINE
347
 
enum buf_io_fix
348
 
buf_page_get_io_fix(
349
 
/*================*/
350
 
        const buf_page_t*       bpage)  /*!< in: pointer to the control block */
351
 
{
352
 
        enum buf_io_fix io_fix = (enum buf_io_fix) bpage->io_fix;
353
 
#ifdef UNIV_DEBUG
354
 
        switch (io_fix) {
355
 
        case BUF_IO_NONE:
356
 
        case BUF_IO_READ:
357
 
        case BUF_IO_WRITE:
358
 
                return(io_fix);
359
 
        }
360
 
        ut_error;
361
 
#endif /* UNIV_DEBUG */
362
 
        return(io_fix);
363
 
}
364
 
 
365
 
/*********************************************************************//**
366
 
Gets the io_fix state of a block.
367
 
@return io_fix state */
368
 
UNIV_INLINE
369
 
enum buf_io_fix
370
 
buf_block_get_io_fix(
371
 
/*=================*/
372
 
        const buf_block_t*      block)  /*!< in: pointer to the control block */
373
 
{
374
 
        return(buf_page_get_io_fix(&block->page));
375
 
}
376
 
 
377
 
/*********************************************************************//**
378
 
Sets the io_fix state of a block. */
379
 
UNIV_INLINE
380
 
void
381
 
buf_page_set_io_fix(
382
 
/*================*/
383
 
        buf_page_t*     bpage,  /*!< in/out: control block */
384
 
        enum buf_io_fix io_fix) /*!< in: io_fix state */
385
 
{
386
 
#ifdef UNIV_DEBUG
387
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
388
 
        ut_ad(buf_pool_mutex_own(buf_pool));
389
 
#endif
390
 
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
391
 
 
392
 
        bpage->io_fix = io_fix;
393
 
        ut_ad(buf_page_get_io_fix(bpage) == io_fix);
394
 
}
395
 
 
396
 
/*********************************************************************//**
397
 
Sets the io_fix state of a block. */
398
 
UNIV_INLINE
399
 
void
400
 
buf_block_set_io_fix(
401
 
/*=================*/
402
 
        buf_block_t*    block,  /*!< in/out: control block */
403
 
        enum buf_io_fix io_fix) /*!< in: io_fix state */
404
 
{
405
 
        buf_page_set_io_fix(&block->page, io_fix);
406
 
}
407
 
 
408
 
/********************************************************************//**
409
 
Determine if a buffer block can be relocated in memory.  The block
410
 
can be dirty, but it must not be I/O-fixed or bufferfixed. */
411
 
UNIV_INLINE
412
 
ibool
413
 
buf_page_can_relocate(
414
 
/*==================*/
415
 
        const buf_page_t*       bpage)  /*!< control block being relocated */
416
 
{
417
 
#ifdef UNIV_DEBUG
418
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
419
 
        ut_ad(buf_pool_mutex_own(buf_pool));
420
 
#endif
421
 
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
422
 
        ut_ad(buf_page_in_file(bpage));
423
 
        ut_ad(bpage->in_LRU_list);
424
 
 
425
 
        return(buf_page_get_io_fix(bpage) == BUF_IO_NONE
426
 
               && bpage->buf_fix_count == 0);
427
 
}
428
 
 
429
 
/*********************************************************************//**
430
 
Determine if a block has been flagged old.
431
 
@return TRUE if old */
432
 
UNIV_INLINE
433
 
ibool
434
 
buf_page_is_old(
435
 
/*============*/
436
 
        const buf_page_t*       bpage)  /*!< in: control block */
437
 
{
438
 
#ifdef UNIV_DEBUG
439
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
440
 
        ut_ad(buf_pool_mutex_own(buf_pool));
441
 
#endif
442
 
        ut_ad(buf_page_in_file(bpage));
443
 
 
444
 
        return(bpage->old);
445
 
}
446
 
 
447
 
/*********************************************************************//**
448
 
Flag a block old. */
449
 
UNIV_INLINE
450
 
void
451
 
buf_page_set_old(
452
 
/*=============*/
453
 
        buf_page_t*     bpage,  /*!< in/out: control block */
454
 
        ibool           old)    /*!< in: old */
455
 
{
456
 
#ifdef UNIV_DEBUG
457
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
458
 
#endif /* UNIV_DEBUG */
459
 
        ut_a(buf_page_in_file(bpage));
460
 
        ut_ad(buf_pool_mutex_own(buf_pool));
461
 
        ut_ad(bpage->in_LRU_list);
462
 
 
463
 
#ifdef UNIV_LRU_DEBUG
464
 
        ut_a((buf_pool->LRU_old_len == 0) == (buf_pool->LRU_old == NULL));
465
 
        /* If a block is flagged "old", the LRU_old list must exist. */
466
 
        ut_a(!old || buf_pool->LRU_old);
467
 
 
468
 
        if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)) {
469
 
                const buf_page_t*       prev = UT_LIST_GET_PREV(LRU, bpage);
470
 
                const buf_page_t*       next = UT_LIST_GET_NEXT(LRU, bpage);
471
 
                if (prev->old == next->old) {
472
 
                        ut_a(prev->old == old);
473
 
                } else {
474
 
                        ut_a(!prev->old);
475
 
                        ut_a(buf_pool->LRU_old == (old ? bpage : next));
476
 
                }
477
 
        }
478
 
#endif /* UNIV_LRU_DEBUG */
479
 
 
480
 
        bpage->old = old;
481
 
}
482
 
 
483
 
/*********************************************************************//**
484
 
Determine the time of first access of a block in the buffer pool.
485
 
@return ut_time_ms() at the time of first access, 0 if not accessed */
486
 
UNIV_INLINE
487
 
unsigned
488
 
buf_page_is_accessed(
489
 
/*=================*/
490
 
        const buf_page_t*       bpage)  /*!< in: control block */
491
 
{
492
 
        ut_ad(buf_page_in_file(bpage));
493
 
 
494
 
        return(bpage->access_time);
495
 
}
496
 
 
497
 
/*********************************************************************//**
498
 
Flag a block accessed. */
499
 
UNIV_INLINE
500
 
void
501
 
buf_page_set_accessed(
502
 
/*==================*/
503
 
        buf_page_t*     bpage,          /*!< in/out: control block */
504
 
        ulint           time_ms)        /*!< in: ut_time_ms() */
505
 
{
506
 
#ifdef UNIV_DEBUG
507
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
508
 
        ut_ad(buf_pool_mutex_own(buf_pool));
509
 
#endif
510
 
        ut_a(buf_page_in_file(bpage));
511
 
 
512
 
        if (!bpage->access_time) {
513
 
                /* Make this the time of the first access. */
514
 
                bpage->access_time = time_ms;
515
 
        }
516
 
}
517
 
 
518
 
/*********************************************************************//**
519
 
Gets the buf_block_t handle of a buffered file block if an uncompressed
520
 
page frame exists, or NULL.
521
 
@return control block, or NULL */
522
 
UNIV_INLINE
523
 
buf_block_t*
524
 
buf_page_get_block(
525
 
/*===============*/
526
 
        buf_page_t*     bpage)  /*!< in: control block, or NULL */
527
 
{
528
 
        if (UNIV_LIKELY(bpage != NULL)) {
529
 
                ut_ad(buf_page_in_file(bpage));
530
 
 
531
 
                if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) {
532
 
                        return((buf_block_t*) bpage);
533
 
                }
534
 
        }
535
 
 
536
 
        return(NULL);
537
 
}
538
 
#endif /* !UNIV_HOTBACKUP */
539
 
 
540
 
#ifdef UNIV_DEBUG
541
 
/*********************************************************************//**
542
 
Gets a pointer to the memory frame of a block.
543
 
@return pointer to the frame */
544
 
UNIV_INLINE
545
 
buf_frame_t*
546
 
buf_block_get_frame(
547
 
/*================*/
548
 
        const buf_block_t*      block)  /*!< in: pointer to the control block */
549
 
{
550
 
        ut_ad(block);
551
 
 
552
 
        switch (buf_block_get_state(block)) {
553
 
        case BUF_BLOCK_ZIP_FREE:
554
 
        case BUF_BLOCK_ZIP_PAGE:
555
 
        case BUF_BLOCK_ZIP_DIRTY:
556
 
        case BUF_BLOCK_NOT_USED:
557
 
                ut_error;
558
 
                break;
559
 
        case BUF_BLOCK_FILE_PAGE:
560
 
# ifndef UNIV_HOTBACKUP
561
 
                ut_a(block->page.buf_fix_count > 0);
562
 
# endif /* !UNIV_HOTBACKUP */
563
 
                /* fall through */
564
 
        case BUF_BLOCK_READY_FOR_USE:
565
 
        case BUF_BLOCK_MEMORY:
566
 
        case BUF_BLOCK_REMOVE_HASH:
567
 
                goto ok;
568
 
        }
569
 
        ut_error;
570
 
ok:
571
 
        return((buf_frame_t*) block->frame);
572
 
}
573
 
#endif /* UNIV_DEBUG */
574
 
 
575
 
/*********************************************************************//**
576
 
Gets the space id of a block.
577
 
@return space id */
578
 
UNIV_INLINE
579
 
ulint
580
 
buf_page_get_space(
581
 
/*===============*/
582
 
        const buf_page_t*       bpage)  /*!< in: pointer to the control block */
583
 
{
584
 
        ut_ad(bpage);
585
 
        ut_a(buf_page_in_file(bpage));
586
 
 
587
 
        return(bpage->space);
588
 
}
589
 
 
590
 
/*********************************************************************//**
591
 
Gets the space id of a block.
592
 
@return space id */
593
 
UNIV_INLINE
594
 
ulint
595
 
buf_block_get_space(
596
 
/*================*/
597
 
        const buf_block_t*      block)  /*!< in: pointer to the control block */
598
 
{
599
 
        ut_ad(block);
600
 
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
601
 
 
602
 
        return(block->page.space);
603
 
}
604
 
 
605
 
/*********************************************************************//**
606
 
Gets the page number of a block.
607
 
@return page number */
608
 
UNIV_INLINE
609
 
ulint
610
 
buf_page_get_page_no(
611
 
/*=================*/
612
 
        const buf_page_t*       bpage)  /*!< in: pointer to the control block */
613
 
{
614
 
        ut_ad(bpage);
615
 
        ut_a(buf_page_in_file(bpage));
616
 
 
617
 
        return(bpage->offset);
618
 
}
619
 
 
620
 
/*********************************************************************//**
621
 
Gets the page number of a block.
622
 
@return page number */
623
 
UNIV_INLINE
624
 
ulint
625
 
buf_block_get_page_no(
626
 
/*==================*/
627
 
        const buf_block_t*      block)  /*!< in: pointer to the control block */
628
 
{
629
 
        ut_ad(block);
630
 
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
631
 
 
632
 
        return(block->page.offset);
633
 
}
634
 
 
635
 
/*********************************************************************//**
636
 
Gets the compressed page size of a block.
637
 
@return compressed page size, or 0 */
638
 
UNIV_INLINE
639
 
ulint
640
 
buf_page_get_zip_size(
641
 
/*==================*/
642
 
        const buf_page_t*       bpage)  /*!< in: pointer to the control block */
643
 
{
644
 
        return(bpage->zip.ssize ? 512 << bpage->zip.ssize : 0);
645
 
}
646
 
 
647
 
/*********************************************************************//**
648
 
Gets the compressed page size of a block.
649
 
@return compressed page size, or 0 */
650
 
UNIV_INLINE
651
 
ulint
652
 
buf_block_get_zip_size(
653
 
/*===================*/
654
 
        const buf_block_t*      block)  /*!< in: pointer to the control block */
655
 
{
656
 
        return(block->page.zip.ssize ? 512 << block->page.zip.ssize : 0);
657
 
}
658
 
 
659
 
#ifndef UNIV_HOTBACKUP
660
 
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
661
 
/*********************************************************************//**
662
 
Gets the compressed page descriptor corresponding to an uncompressed page
663
 
if applicable.
664
 
@return compressed page descriptor, or NULL */
665
 
UNIV_INLINE
666
 
const page_zip_des_t*
667
 
buf_frame_get_page_zip(
668
 
/*===================*/
669
 
        const byte*     ptr)    /*!< in: pointer to the page */
670
 
{
671
 
        return(buf_block_get_page_zip(buf_block_align(ptr)));
672
 
}
673
 
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
674
 
#endif /* !UNIV_HOTBACKUP */
675
 
 
676
 
/**********************************************************************//**
677
 
Gets the space id, page offset, and byte offset within page of a
678
 
pointer pointing to a buffer frame containing a file page. */
679
 
UNIV_INLINE
680
 
void
681
 
buf_ptr_get_fsp_addr(
682
 
/*=================*/
683
 
        const void*     ptr,    /*!< in: pointer to a buffer frame */
684
 
        ulint*          space,  /*!< out: space id */
685
 
        fil_addr_t*     addr)   /*!< out: page offset and byte offset */
686
 
{
687
 
        const page_t*   page = (const page_t*) ut_align_down(ptr,
688
 
                                                             UNIV_PAGE_SIZE);
689
 
 
690
 
        *space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
691
 
        addr->page = mach_read_from_4(page + FIL_PAGE_OFFSET);
692
 
        addr->boffset = ut_align_offset(ptr, UNIV_PAGE_SIZE);
693
 
}
694
 
 
695
 
#ifndef UNIV_HOTBACKUP
696
 
/**********************************************************************//**
697
 
Gets the hash value of the page the pointer is pointing to. This can be used
698
 
in searches in the lock hash table.
699
 
@return lock hash value */
700
 
UNIV_INLINE
701
 
ulint
702
 
buf_block_get_lock_hash_val(
703
 
/*========================*/
704
 
        const buf_block_t*      block)  /*!< in: block */
705
 
{
706
 
        ut_ad(block);
707
 
        ut_ad(buf_page_in_file(&block->page));
708
 
#ifdef UNIV_SYNC_DEBUG
709
 
        ut_ad(rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_EXCLUSIVE)
710
 
              || rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_SHARED));
711
 
#endif /* UNIV_SYNC_DEBUG */
712
 
        return(block->lock_hash_val);
713
 
}
714
 
 
715
 
/********************************************************************//**
716
 
Frees a buffer block which does not contain a file page. */
717
 
UNIV_INLINE
718
 
void
719
 
buf_block_free(
720
 
/*===========*/
721
 
        buf_block_t*    block)  /*!< in, own: block to be freed */
722
 
{
723
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage((buf_page_t*)block);
724
 
 
725
 
        buf_pool_mutex_enter(buf_pool);
726
 
 
727
 
        mutex_enter(&block->mutex);
728
 
 
729
 
        ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
730
 
 
731
 
        buf_LRU_block_free_non_file_page(block);
732
 
 
733
 
        mutex_exit(&block->mutex);
734
 
 
735
 
        buf_pool_mutex_exit(buf_pool);
736
 
}
737
 
#endif /* !UNIV_HOTBACKUP */
738
 
 
739
 
/*********************************************************************//**
740
 
Copies contents of a buffer frame to a given buffer.
741
 
@return buf */
742
 
UNIV_INLINE
743
 
byte*
744
 
buf_frame_copy(
745
 
/*===========*/
746
 
        byte*                   buf,    /*!< in: buffer to copy to */
747
 
        const buf_frame_t*      frame)  /*!< in: buffer frame */
748
 
{
749
 
        ut_ad(buf && frame);
750
 
 
751
 
        ut_memcpy(buf, frame, UNIV_PAGE_SIZE);
752
 
 
753
 
        return(buf);
754
 
}
755
 
 
756
 
#ifndef UNIV_HOTBACKUP
757
 
/********************************************************************//**
758
 
Calculates a folded value of a file page address to use in the page hash
759
 
table.
760
 
@return the folded value */
761
 
UNIV_INLINE
762
 
ulint
763
 
buf_page_address_fold(
764
 
/*==================*/
765
 
        ulint   space,  /*!< in: space id */
766
 
        ulint   offset) /*!< in: offset of the page within space */
767
 
{
768
 
        return((space << 20) + space + offset);
769
 
}
770
 
 
771
 
/********************************************************************//**
772
 
Gets the youngest modification log sequence number for a frame.
773
 
Returns zero if not file page or no modification occurred yet.
774
 
@return newest modification to page */
775
 
UNIV_INLINE
776
 
ib_uint64_t
777
 
buf_page_get_newest_modification(
778
 
/*=============================*/
779
 
        const buf_page_t*       bpage)  /*!< in: block containing the
780
 
                                        page frame */
781
 
{
782
 
        ib_uint64_t     lsn;
783
 
        mutex_t*        block_mutex = buf_page_get_mutex(bpage);
784
 
 
785
 
        mutex_enter(block_mutex);
786
 
 
787
 
        if (buf_page_in_file(bpage)) {
788
 
                lsn = bpage->newest_modification;
789
 
        } else {
790
 
                lsn = 0;
791
 
        }
792
 
 
793
 
        mutex_exit(block_mutex);
794
 
 
795
 
        return(lsn);
796
 
}
797
 
 
798
 
/********************************************************************//**
799
 
Increments the modify clock of a frame by 1. The caller must (1) own the
800
 
buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
801
 
on the block. */
802
 
UNIV_INLINE
803
 
void
804
 
buf_block_modify_clock_inc(
805
 
/*=======================*/
806
 
        buf_block_t*    block)  /*!< in: block */
807
 
{
808
 
#ifdef UNIV_SYNC_DEBUG
809
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage((buf_page_t*)block);
810
 
 
811
 
        ut_ad((buf_pool_mutex_own(buf_pool)
812
 
               && (block->page.buf_fix_count == 0))
813
 
              || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
814
 
#endif /* UNIV_SYNC_DEBUG */
815
 
 
816
 
        block->modify_clock++;
817
 
}
818
 
 
819
 
/********************************************************************//**
820
 
Returns the value of the modify clock. The caller must have an s-lock
821
 
or x-lock on the block.
822
 
@return value */
823
 
UNIV_INLINE
824
 
ib_uint64_t
825
 
buf_block_get_modify_clock(
826
 
/*=======================*/
827
 
        buf_block_t*    block)  /*!< in: block */
828
 
{
829
 
#ifdef UNIV_SYNC_DEBUG
830
 
        ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
831
 
              || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
832
 
#endif /* UNIV_SYNC_DEBUG */
833
 
 
834
 
        return(block->modify_clock);
835
 
}
836
 
 
837
 
/*******************************************************************//**
838
 
Increments the bufferfix count. */
839
 
UNIV_INLINE
840
 
void
841
 
buf_block_buf_fix_inc_func(
842
 
/*=======================*/
843
 
#ifdef UNIV_SYNC_DEBUG
844
 
        const char*     file,   /*!< in: file name */
845
 
        ulint           line,   /*!< in: line */
846
 
#endif /* UNIV_SYNC_DEBUG */
847
 
        buf_block_t*    block)  /*!< in/out: block to bufferfix */
848
 
{
849
 
#ifdef UNIV_SYNC_DEBUG
850
 
        ibool   ret;
851
 
 
852
 
        ret = rw_lock_s_lock_nowait(&(block->debug_latch), file, line);
853
 
        ut_a(ret);
854
 
#endif /* UNIV_SYNC_DEBUG */
855
 
        ut_ad(mutex_own(&block->mutex));
856
 
 
857
 
        block->page.buf_fix_count++;
858
 
}
859
 
#ifdef UNIV_SYNC_DEBUG
860
 
/** Increments the bufferfix count.
861
 
@param b        in/out: block to bufferfix
862
 
@param f        in: file name where requested
863
 
@param l        in: line number where requested */
864
 
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
865
 
#else /* UNIV_SYNC_DEBUG */
866
 
/** Increments the bufferfix count.
867
 
@param b        in/out: block to bufferfix
868
 
@param f        in: file name where requested
869
 
@param l        in: line number where requested */
870
 
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
871
 
#endif /* UNIV_SYNC_DEBUG */
872
 
 
873
 
/*******************************************************************//**
874
 
Decrements the bufferfix count. */
875
 
UNIV_INLINE
876
 
void
877
 
buf_block_buf_fix_dec(
878
 
/*==================*/
879
 
        buf_block_t*    block)  /*!< in/out: block to bufferunfix */
880
 
{
881
 
        ut_ad(mutex_own(&block->mutex));
882
 
 
883
 
        block->page.buf_fix_count--;
884
 
#ifdef UNIV_SYNC_DEBUG
885
 
        rw_lock_s_unlock(&block->debug_latch);
886
 
#endif
887
 
}
888
 
 
889
 
/******************************************************************//**
890
 
Returns the buffer pool instance given a page instance
891
 
@return buf_pool */
892
 
UNIV_INLINE
893
 
buf_pool_t*
894
 
buf_pool_from_bpage(
895
 
/*================*/
896
 
        const buf_page_t*       bpage) /*!< in: buffer pool page */
897
 
{
898
 
        /* Every page must be in some buffer pool. */
899
 
        ut_ad(bpage->buf_pool != NULL);
900
 
 
901
 
        return(bpage->buf_pool);
902
 
}
903
 
 
904
 
/******************************************************************//**
905
 
Returns the buffer pool instance given a block instance
906
 
@return buf_pool */
907
 
UNIV_INLINE
908
 
buf_pool_t*
909
 
buf_pool_from_block(
910
 
/*================*/
911
 
        const buf_block_t*      block) /*!< in: block */
912
 
{
913
 
        return(buf_pool_from_bpage(&block->page));
914
 
}
915
 
 
916
 
/******************************************************************//**
917
 
Returns the buffer pool instance given space and offset of page
918
 
@return buffer pool */
919
 
UNIV_INLINE
920
 
buf_pool_t*
921
 
buf_pool_get(
922
 
/*==========*/
923
 
        ulint   space,  /*!< in: space id */
924
 
        ulint   offset) /*!< in: offset of the page within space */
925
 
{
926
 
        ulint   fold;
927
 
        ulint   index;
928
 
        ulint   ignored_offset;
929
 
 
930
 
        ignored_offset = offset >> 6; /* 2log of BUF_READ_AHEAD_AREA (64)*/
931
 
        fold = buf_page_address_fold(space, ignored_offset);
932
 
        index = fold % srv_buf_pool_instances;
933
 
        return buf_pool_ptr[index];
934
 
}
935
 
 
936
 
/******************************************************************//**
937
 
Returns the buffer pool instance given its array index
938
 
@return buffer pool */
939
 
UNIV_INLINE
940
 
buf_pool_t*
941
 
buf_pool_from_array(
942
 
/*================*/
943
 
        ulint   index)          /*!< in: array index to get
944
 
                                buffer pool instance from */
945
 
{
946
 
        return buf_pool_ptr[index];
947
 
}
948
 
 
949
 
/******************************************************************//**
950
 
Returns the control block of a file page, NULL if not found.
951
 
@return block, NULL if not found */
952
 
UNIV_INLINE
953
 
buf_page_t*
954
 
buf_page_hash_get_low(
955
 
/*==================*/
956
 
        buf_pool_t*     buf_pool,       /*!< buffer pool instance */
957
 
        ulint           space,          /*!< in: space id */
958
 
        ulint           offset,         /*!< in: offset of the page
959
 
                                        within space */
960
 
        ulint           fold)           /*!< in: buf_page_address_fold(
961
 
                                        space, offset) */
962
 
{
963
 
        buf_page_t*     bpage;
964
 
 
965
 
        ut_ad(buf_pool);
966
 
        ut_ad(buf_pool_mutex_own(buf_pool));
967
 
        ut_ad(fold == buf_page_address_fold(space, offset));
968
 
 
969
 
        /* Look for the page in the hash table */
970
 
 
971
 
        HASH_SEARCH(hash, buf_pool->page_hash, fold, buf_page_t*, bpage,
972
 
                    ut_ad(bpage->in_page_hash && !bpage->in_zip_hash
973
 
                          && buf_page_in_file(bpage)),
974
 
                    bpage->space == space && bpage->offset == offset);
975
 
        if (bpage) {
976
 
                ut_a(buf_page_in_file(bpage));
977
 
                ut_ad(bpage->in_page_hash);
978
 
                ut_ad(!bpage->in_zip_hash);
979
 
#if UNIV_WORD_SIZE == 4
980
 
                /* On 32-bit systems, there is no padding in
981
 
                buf_page_t.  On other systems, Valgrind could complain
982
 
                about uninitialized pad bytes. */
983
 
                UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
984
 
#endif
985
 
        }
986
 
 
987
 
        return(bpage);
988
 
}
989
 
 
990
 
/******************************************************************//**
991
 
Returns the control block of a file page, NULL if not found.
992
 
@return block, NULL if not found or not a real control block */
993
 
UNIV_INLINE
994
 
buf_page_t*
995
 
buf_page_hash_get(
996
 
/*==============*/
997
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
998
 
        ulint           space,          /*!< in: space id */
999
 
        ulint           offset)         /*!< in: offset of the page
1000
 
                                        within space */
1001
 
{
1002
 
        buf_page_t*     bpage;
1003
 
        ulint           fold    = buf_page_address_fold(space, offset);
1004
 
 
1005
 
        bpage   = buf_page_hash_get_low(buf_pool, space, offset, fold);
1006
 
 
1007
 
        if (bpage && buf_pool_watch_is_sentinel(buf_pool, bpage)) {
1008
 
                bpage = NULL;
1009
 
        }
1010
 
 
1011
 
        return(bpage);
1012
 
}
1013
 
 
1014
 
/******************************************************************//**
1015
 
Returns the control block of a file page, NULL if not found
1016
 
or an uncompressed page frame does not exist.
1017
 
@return block, NULL if not found */
1018
 
UNIV_INLINE
1019
 
buf_block_t*
1020
 
buf_block_hash_get(
1021
 
/*===============*/
1022
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
1023
 
        ulint           space,          /*!< in: space id */
1024
 
        ulint           offset)         /*!< in: offset of the page
1025
 
                                        within space */
1026
 
{
1027
 
        buf_block_t*    block;
1028
 
 
1029
 
        block = buf_page_get_block(buf_page_hash_get(buf_pool, space, offset));
1030
 
 
1031
 
        return(block);
1032
 
}
1033
 
 
1034
 
/********************************************************************//**
1035
 
Returns TRUE if the page can be found in the buffer pool hash table.
1036
 
 
1037
 
NOTE that it is possible that the page is not yet read from disk,
1038
 
though.
1039
 
 
1040
 
@return TRUE if found in the page hash table */
1041
 
UNIV_INLINE
1042
 
ibool
1043
 
buf_page_peek(
1044
 
/*==========*/
1045
 
        ulint   space,  /*!< in: space id */
1046
 
        ulint   offset) /*!< in: page number */
1047
 
{
1048
 
        const buf_page_t*       bpage;
1049
 
        buf_pool_t*             buf_pool = buf_pool_get(space, offset);
1050
 
 
1051
 
        buf_pool_mutex_enter(buf_pool);
1052
 
 
1053
 
        bpage = buf_page_hash_get(buf_pool, space, offset);
1054
 
 
1055
 
        buf_pool_mutex_exit(buf_pool);
1056
 
 
1057
 
        return(bpage != NULL);
1058
 
}
1059
 
 
1060
 
/********************************************************************//**
1061
 
Releases a compressed-only page acquired with buf_page_get_zip(). */
1062
 
UNIV_INLINE
1063
 
void
1064
 
buf_page_release_zip(
1065
 
/*=================*/
1066
 
        buf_page_t*     bpage)          /*!< in: buffer block */
1067
 
{
1068
 
        buf_block_t*    block;
1069
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1070
 
 
1071
 
        ut_ad(bpage);
1072
 
        ut_a(bpage->buf_fix_count > 0);
1073
 
 
1074
 
        switch (buf_page_get_state(bpage)) {
1075
 
        case BUF_BLOCK_ZIP_PAGE:
1076
 
        case BUF_BLOCK_ZIP_DIRTY:
1077
 
                mutex_enter(&buf_pool->zip_mutex);
1078
 
                bpage->buf_fix_count--;
1079
 
                mutex_exit(&buf_pool->zip_mutex);
1080
 
                return;
1081
 
        case BUF_BLOCK_FILE_PAGE:
1082
 
                block = (buf_block_t*) bpage;
1083
 
                mutex_enter(&block->mutex);
1084
 
#ifdef UNIV_SYNC_DEBUG
1085
 
                rw_lock_s_unlock(&block->debug_latch);
1086
 
#endif
1087
 
                bpage->buf_fix_count--;
1088
 
                mutex_exit(&block->mutex);
1089
 
                return;
1090
 
        case BUF_BLOCK_ZIP_FREE:
1091
 
        case BUF_BLOCK_NOT_USED:
1092
 
        case BUF_BLOCK_READY_FOR_USE:
1093
 
        case BUF_BLOCK_MEMORY:
1094
 
        case BUF_BLOCK_REMOVE_HASH:
1095
 
                break;
1096
 
        }
1097
 
 
1098
 
        
1099
 
        ut_error;
1100
 
}
1101
 
 
1102
 
/********************************************************************//**
1103
 
Decrements the bufferfix count of a buffer control block and releases
1104
 
a latch, if specified. */
1105
 
UNIV_INLINE
1106
 
void
1107
 
buf_page_release(
1108
 
/*=============*/
1109
 
        buf_block_t*    block,          /*!< in: buffer block */
1110
 
        ulint           rw_latch)       /*!< in: RW_S_LATCH, RW_X_LATCH,
1111
 
                                        RW_NO_LATCH */
1112
 
{
1113
 
        ut_ad(block);
1114
 
 
1115
 
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
1116
 
        ut_a(block->page.buf_fix_count > 0);
1117
 
 
1118
 
        mutex_enter(&block->mutex);
1119
 
 
1120
 
#ifdef UNIV_SYNC_DEBUG
1121
 
        rw_lock_s_unlock(&(block->debug_latch));
1122
 
#endif
1123
 
        block->page.buf_fix_count--;
1124
 
 
1125
 
        mutex_exit(&block->mutex);
1126
 
 
1127
 
        if (rw_latch == RW_S_LATCH) {
1128
 
                rw_lock_s_unlock(&(block->lock));
1129
 
        } else if (rw_latch == RW_X_LATCH) {
1130
 
                rw_lock_x_unlock(&(block->lock));
1131
 
        }
1132
 
}
1133
 
 
1134
 
#ifdef UNIV_SYNC_DEBUG
1135
 
/*********************************************************************//**
1136
 
Adds latch level info for the rw-lock protecting the buffer frame. This
1137
 
should be called in the debug version after a successful latching of a
1138
 
page if we know the latching order level of the acquired latch. */
1139
 
UNIV_INLINE
1140
 
void
1141
 
buf_block_dbg_add_level(
1142
 
/*====================*/
1143
 
        buf_block_t*    block,  /*!< in: buffer page
1144
 
                                where we have acquired latch */
1145
 
        ulint           level)  /*!< in: latching order level */
1146
 
{
1147
 
        sync_thread_add_level(&block->lock, level);
1148
 
}
1149
 
#endif /* UNIV_SYNC_DEBUG */
1150
 
/********************************************************************//**
1151
 
Acquire mutex on all buffer pool instances. */
1152
 
UNIV_INLINE
1153
 
void
1154
 
buf_pool_mutex_enter_all(void)
1155
 
/*==========================*/
1156
 
{
1157
 
        ulint   i;
1158
 
 
1159
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
1160
 
                buf_pool_t*     buf_pool;
1161
 
 
1162
 
                buf_pool = buf_pool_from_array(i);
1163
 
                buf_pool_mutex_enter(buf_pool);
1164
 
        }
1165
 
}
1166
 
 
1167
 
/********************************************************************//**
1168
 
Release mutex on all buffer pool instances. */
1169
 
UNIV_INLINE
1170
 
void
1171
 
buf_pool_mutex_exit_all(void)
1172
 
/*=========================*/
1173
 
{
1174
 
        ulint   i;
1175
 
 
1176
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
1177
 
                buf_pool_t*     buf_pool;
1178
 
 
1179
 
                buf_pool = buf_pool_from_array(i);
1180
 
                buf_pool_mutex_exit(buf_pool);
1181
 
        }
1182
 
}
1183
 
#endif /* !UNIV_HOTBACKUP */