~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Tags: innodb-plugin-1.0.1
Imported 1.0.1 with clean - with no changes.

Show diffs side-by-side

added added

removed removed

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