~ubuntu-branches/ubuntu/precise/mysql-5.5/precise-201203300109

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Clint Byrum
  • Date: 2011-11-08 11:31:13 UTC
  • Revision ID: package-import@ubuntu.com-20111108113113-3ulw01fvi4vn8m25
Tags: upstream-5.5.17
ImportĀ upstreamĀ versionĀ 5.5.17

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