~gaul/percona-data-recovery-tool-for-innodb/prerequisites

« back to all changes in this revision

Viewing changes to mysql-source/innobase/include/buf0buf.ic

  • Committer: Aleksandr Kuzminsky
  • Date: 2010-01-14 13:05:06 UTC
  • mfrom: (1.1.1 page-signature-check)
  • Revision ID: aleksandr.kuzminsky@percona.com-20100114130506-72t6jxtll15gk3pp
Added InnoDB page signature check.
At the beginning of InnoDB page (type FIL_PAGE_INODE) there are infimum and supremum records.
They are located in fixed position depending on InnoDB page format(REDUNDANT (4.x and 5.x versions) or COMPACT(5.x only)).

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
#ifdef UNIV_DEBUG
 
15
extern ulint            buf_dbg_counter; /* This is used to insert validation
 
16
                                        operations in execution in the
 
17
                                        debug version */
 
18
#endif /* UNIV_DEBUG */
 
19
/************************************************************************
 
20
Recommends a move of a block to the start of the LRU list if there is danger
 
21
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
 
22
mutex. */
 
23
UNIV_INLINE
 
24
ibool
 
25
buf_block_peek_if_too_old(
 
26
/*======================*/
 
27
                                /* out: TRUE if should be made younger */
 
28
        buf_block_t*    block)  /* in: block to make younger */
 
29
{
 
30
        return(buf_pool->freed_page_clock >= block->freed_page_clock
 
31
                                + 1 + (buf_pool->curr_size / 1024));
 
32
}
 
33
 
 
34
/*************************************************************************
 
35
Gets the current size of buffer buf_pool in bytes. In the case of AWE, the
 
36
size of AWE window (= the frames). */
 
37
UNIV_INLINE
 
38
ulint
 
39
buf_pool_get_curr_size(void)
 
40
/*========================*/
 
41
                        /* out: size in bytes */
 
42
{
 
43
        return((buf_pool->n_frames) * UNIV_PAGE_SIZE);
 
44
}       
 
45
 
 
46
/*************************************************************************
 
47
Gets the maximum size of buffer buf_pool in bytes. In the case of AWE, the
 
48
size of AWE window (= the frames). */
 
49
UNIV_INLINE
 
50
ulint
 
51
buf_pool_get_max_size(void)
 
52
/*=======================*/
 
53
                        /* out: size in bytes */
 
54
{
 
55
        return((buf_pool->n_frames) * UNIV_PAGE_SIZE);
 
56
}       
 
57
 
 
58
/***********************************************************************
 
59
Accessor function for block array. */
 
60
UNIV_INLINE
 
61
buf_block_t*
 
62
buf_pool_get_nth_block(
 
63
/*===================*/
 
64
                                /* out: pointer to block */
 
65
        buf_pool_t*     buf_pool,/* in: buf_pool */
 
66
        ulint           i)      /* in: index of the block */
 
67
{
 
68
        ut_ad(buf_pool);
 
69
        ut_ad(i < buf_pool->max_size);
 
70
 
 
71
        return(i + buf_pool->blocks);
 
72
}       
 
73
 
 
74
/***********************************************************************
 
75
Checks if a pointer points to the block array of the buffer pool (blocks, not
 
76
the frames). */
 
77
UNIV_INLINE
 
78
ibool
 
79
buf_pool_is_block(
 
80
/*==============*/
 
81
                        /* out: TRUE if pointer to block */
 
82
        void*   ptr)    /* in: pointer to memory */
 
83
{
 
84
        if ((buf_pool->blocks <= (buf_block_t*)ptr)
 
85
            && ((buf_block_t*)ptr < buf_pool->blocks + buf_pool->max_size)) {
 
86
 
 
87
                return(TRUE);
 
88
        }
 
89
 
 
90
        return(FALSE);
 
91
}       
 
92
 
 
93
/************************************************************************
 
94
Gets the smallest oldest_modification lsn for any page in the pool. Returns
 
95
ut_dulint_zero if all modified pages have been flushed to disk. */
 
96
UNIV_INLINE
 
97
dulint
 
98
buf_pool_get_oldest_modification(void)
 
99
/*==================================*/
 
100
                                /* out: oldest modification in pool,
 
101
                                ut_dulint_zero if none */
 
102
{
 
103
        buf_block_t*    block;
 
104
        dulint          lsn;
 
105
        
 
106
        mutex_enter(&(buf_pool->mutex));
 
107
 
 
108
        block = UT_LIST_GET_LAST(buf_pool->flush_list);
 
109
 
 
110
        if (block == NULL) {
 
111
                lsn = ut_dulint_zero;
 
112
        } else {
 
113
                lsn = block->oldest_modification;
 
114
        }
 
115
 
 
116
        mutex_exit(&(buf_pool->mutex));
 
117
 
 
118
        return(lsn);
 
119
}
 
120
 
 
121
/***********************************************************************
 
122
Increments the buf_pool clock by one and returns its new value. Remember
 
123
that in the 32 bit version the clock wraps around at 4 billion! */
 
124
UNIV_INLINE
 
125
ulint
 
126
buf_pool_clock_tic(void)
 
127
/*====================*/
 
128
                        /* out: new clock value */
 
129
{
 
130
#ifdef UNIV_SYNC_DEBUG
 
131
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
132
#endif /* UNIV_SYNC_DEBUG */
 
133
        
 
134
        buf_pool->ulint_clock++;
 
135
 
 
136
        return(buf_pool->ulint_clock);
 
137
}
 
138
 
 
139
/*************************************************************************
 
140
Gets a pointer to the memory frame of a block. */
 
141
UNIV_INLINE
 
142
buf_frame_t*
 
143
buf_block_get_frame(
 
144
/*================*/
 
145
                                /* out: pointer to the frame */
 
146
        buf_block_t*    block)  /* in: pointer to the control block */
 
147
{
 
148
        ut_ad(block);
 
149
        ut_ad(block >= buf_pool->blocks);
 
150
        ut_ad(block < buf_pool->blocks + buf_pool->max_size);
 
151
        ut_ad(block->state != BUF_BLOCK_NOT_USED); 
 
152
        ut_ad((block->state != BUF_BLOCK_FILE_PAGE) 
 
153
              || (block->buf_fix_count > 0));
 
154
        
 
155
        return(block->frame);
 
156
}       
 
157
 
 
158
/*************************************************************************
 
159
Gets the space id of a block. */
 
160
UNIV_INLINE
 
161
ulint
 
162
buf_block_get_space(
 
163
/*================*/
 
164
                                /* out: space id */
 
165
        buf_block_t*    block)  /* in: pointer to the control block */
 
166
{
 
167
        ut_ad(block);
 
168
        ut_ad(block >= buf_pool->blocks);
 
169
        ut_ad(block < buf_pool->blocks + buf_pool->max_size);
 
170
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
171
        ut_ad(block->buf_fix_count > 0);
 
172
        
 
173
        return(block->space);
 
174
}       
 
175
 
 
176
/*************************************************************************
 
177
Gets the page number of a block. */
 
178
UNIV_INLINE
 
179
ulint
 
180
buf_block_get_page_no(
 
181
/*==================*/
 
182
                                /* out: page number */
 
183
        buf_block_t*    block)  /* in: pointer to the control block */
 
184
{
 
185
        ut_ad(block);
 
186
        ut_ad(block >= buf_pool->blocks);
 
187
        ut_ad(block < buf_pool->blocks + buf_pool->max_size);
 
188
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
189
        ut_ad(block->buf_fix_count > 0);
 
190
        
 
191
        return(block->offset);
 
192
}       
 
193
 
 
194
/***********************************************************************
 
195
Gets the block to whose frame the pointer is pointing to. */
 
196
UNIV_INLINE
 
197
buf_block_t*
 
198
buf_block_align(
 
199
/*============*/
 
200
                        /* out: pointer to block */
 
201
        byte*   ptr)    /* in: pointer to a frame */
 
202
{
 
203
        buf_block_t*    block;
 
204
        buf_frame_t*    frame_zero;
 
205
 
 
206
        ut_ad(ptr);
 
207
 
 
208
        frame_zero = buf_pool->frame_zero;
 
209
 
 
210
        if (UNIV_UNLIKELY((ulint)ptr < (ulint)frame_zero)
 
211
            || UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) {
 
212
 
 
213
                ut_print_timestamp(stderr);     
 
214
                fprintf(stderr,
 
215
"InnoDB: Error: trying to access a stray pointer %p\n"
 
216
"InnoDB: buf pool start is at %p, end at %p\n"
 
217
"InnoDB: Probable reason is database corruption or memory\n"
 
218
"InnoDB: corruption. If this happens in an InnoDB database recovery, see\n"
 
219
"InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html\n"
 
220
"InnoDB: how to force recovery.\n",
 
221
                        ptr, frame_zero,
 
222
                        buf_pool->high_end);
 
223
                ut_error;
 
224
        }
 
225
        
 
226
        block = *(buf_pool->blocks_of_frames + (((ulint)(ptr - frame_zero))
 
227
                                                >> UNIV_PAGE_SIZE_SHIFT));
 
228
        return(block);
 
229
}       
 
230
 
 
231
/***********************************************************************
 
232
Gets the frame the pointer is pointing to. */
 
233
UNIV_INLINE
 
234
buf_frame_t*
 
235
buf_frame_align(
 
236
/*============*/
 
237
                        /* out: pointer to frame */
 
238
        byte*   ptr)    /* in: pointer to a frame */
 
239
{
 
240
        buf_frame_t*    frame;
 
241
 
 
242
        ut_ad(ptr);
 
243
 
 
244
        frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
 
245
 
 
246
        if (UNIV_UNLIKELY((ulint)frame < (ulint)(buf_pool->frame_zero))
 
247
            || UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) {
 
248
 
 
249
                ut_print_timestamp(stderr);     
 
250
                fprintf(stderr,
 
251
"InnoDB: Error: trying to access a stray pointer %p\n"
 
252
"InnoDB: buf pool start is at %p, end at %p\n"
 
253
"InnoDB: Probable reason is database corruption or memory\n"
 
254
"InnoDB: corruption. If this happens in an InnoDB database recovery, see\n"
 
255
"InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html\n"
 
256
"InnoDB: how to force recovery.\n",
 
257
                        ptr, buf_pool->frame_zero,
 
258
                        buf_pool->high_end);
 
259
                ut_error;
 
260
        }
 
261
 
 
262
        return(frame);
 
263
}
 
264
 
 
265
/**************************************************************************
 
266
Gets the page number of a pointer pointing within a buffer frame containing
 
267
a file page. */
 
268
UNIV_INLINE
 
269
ulint
 
270
buf_frame_get_page_no(
 
271
/*==================*/
 
272
                        /* out: page number */
 
273
        byte*   ptr)    /* in: pointer to within a buffer frame */
 
274
{
 
275
        return(buf_block_get_page_no(buf_block_align(ptr)));
 
276
}
 
277
 
 
278
/**************************************************************************
 
279
Gets the space id of a pointer pointing within a buffer frame containing a
 
280
file page. */
 
281
UNIV_INLINE
 
282
ulint
 
283
buf_frame_get_space_id(
 
284
/*===================*/
 
285
                        /* out: space id */
 
286
        byte*   ptr)    /* in: pointer to within a buffer frame */
 
287
{
 
288
        return(buf_block_get_space(buf_block_align(ptr)));
 
289
}
 
290
 
 
291
/**************************************************************************
 
292
Gets the space id, page offset, and byte offset within page of a
 
293
pointer pointing to a buffer frame containing a file page. */
 
294
UNIV_INLINE
 
295
void
 
296
buf_ptr_get_fsp_addr(
 
297
/*=================*/
 
298
        byte*           ptr,    /* in: pointer to a buffer frame */
 
299
        ulint*          space,  /* out: space id */
 
300
        fil_addr_t*     addr)   /* out: page offset and byte offset */
 
301
{
 
302
        buf_block_t*    block;
 
303
 
 
304
        block = buf_block_align(ptr);
 
305
 
 
306
        *space = buf_block_get_space(block);
 
307
        addr->page = buf_block_get_page_no(block);
 
308
        addr->boffset = ptr - buf_frame_align(ptr);
 
309
}
 
310
 
 
311
/**************************************************************************
 
312
Gets the hash value of the page the pointer is pointing to. This can be used
 
313
in searches in the lock hash table. */
 
314
UNIV_INLINE
 
315
ulint
 
316
buf_frame_get_lock_hash_val(
 
317
/*========================*/
 
318
                        /* out: lock hash value */
 
319
        byte*   ptr)    /* in: pointer to within a buffer frame */
 
320
{
 
321
        buf_block_t*    block;
 
322
 
 
323
        block = buf_block_align(ptr);
 
324
 
 
325
        return(block->lock_hash_val);
 
326
}
 
327
 
 
328
/**************************************************************************
 
329
Gets the mutex number protecting the page record lock hash chain in the lock
 
330
table. */
 
331
UNIV_INLINE
 
332
mutex_t*
 
333
buf_frame_get_mutex(
 
334
/*================*/
 
335
                        /* out: mutex */
 
336
        byte*   ptr)    /* in: pointer to within a buffer frame */
 
337
{
 
338
        buf_block_t*    block;
 
339
 
 
340
        block = buf_block_align(ptr);
 
341
 
 
342
        return(&block->mutex);
 
343
}
 
344
 
 
345
/*************************************************************************
 
346
Copies contents of a buffer frame to a given buffer. */
 
347
UNIV_INLINE
 
348
byte*
 
349
buf_frame_copy(
 
350
/*===========*/
 
351
                                /* out: buf */
 
352
        byte*           buf,    /* in: buffer to copy to */
 
353
        buf_frame_t*    frame)  /* in: buffer frame */
 
354
{
 
355
        ut_ad(buf && frame);
 
356
 
 
357
        ut_memcpy(buf, frame, UNIV_PAGE_SIZE);
 
358
 
 
359
        return(buf);
 
360
}
 
361
 
 
362
/************************************************************************
 
363
Calculates a folded value of a file page address to use in the page hash
 
364
table. */
 
365
UNIV_INLINE
 
366
ulint
 
367
buf_page_address_fold(
 
368
/*==================*/
 
369
                        /* out: the folded value */
 
370
        ulint   space,  /* in: space id */
 
371
        ulint   offset) /* in: offset of the page within space */
 
372
{
 
373
        return((space << 20) + space + offset);
 
374
}       
 
375
 
 
376
/************************************************************************
 
377
This function is used to get info if there is an io operation
 
378
going on on a buffer page. */
 
379
UNIV_INLINE
 
380
ibool
 
381
buf_page_io_query(
 
382
/*==============*/
 
383
                                /* out: TRUE if io going on */
 
384
        buf_block_t*    block)  /* in: buf_pool block, must be bufferfixed */
 
385
{
 
386
        mutex_enter(&(buf_pool->mutex));
 
387
 
 
388
        ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
 
389
        ut_ad(block->buf_fix_count > 0);
 
390
 
 
391
        if (block->io_fix != 0) {
 
392
                mutex_exit(&(buf_pool->mutex));
 
393
 
 
394
                return(TRUE);
 
395
        }
 
396
 
 
397
        mutex_exit(&(buf_pool->mutex));
 
398
 
 
399
        return(FALSE);
 
400
}
 
401
 
 
402
/************************************************************************
 
403
Gets the youngest modification log sequence number for a frame. Returns zero
 
404
if not a file page or no modification occurred yet. */
 
405
UNIV_INLINE
 
406
dulint
 
407
buf_frame_get_newest_modification(
 
408
/*==============================*/
 
409
                                /* out: newest modification to the page */
 
410
        buf_frame_t*    frame)  /* in: pointer to a frame */
 
411
{
 
412
        buf_block_t*    block;
 
413
        dulint          lsn;
 
414
        
 
415
        ut_ad(frame);
 
416
 
 
417
        block = buf_block_align(frame);
 
418
 
 
419
        mutex_enter(&(buf_pool->mutex));
 
420
 
 
421
        if (block->state == BUF_BLOCK_FILE_PAGE) {
 
422
                lsn = block->newest_modification;
 
423
        } else {
 
424
                lsn = ut_dulint_zero;
 
425
        }
 
426
 
 
427
        mutex_exit(&(buf_pool->mutex));
 
428
 
 
429
        return(lsn);
 
430
}
 
431
 
 
432
/************************************************************************
 
433
Increments the modify clock of a frame by 1. The caller must (1) own the
 
434
buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
 
435
on the block. */
 
436
UNIV_INLINE
 
437
dulint
 
438
buf_frame_modify_clock_inc(
 
439
/*=======================*/
 
440
                                /* out: new value */
 
441
        buf_frame_t*    frame)  /* in: pointer to a frame */
 
442
{
 
443
        buf_block_t*    block;
 
444
 
 
445
        ut_ad(frame);
 
446
 
 
447
        block = buf_block_align(frame);
 
448
 
 
449
#ifdef UNIV_SYNC_DEBUG
 
450
        ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0))
 
451
              || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
 
452
#endif /*UNIV_SYNC_DEBUG */
 
453
 
 
454
        UT_DULINT_INC(block->modify_clock);
 
455
 
 
456
        return(block->modify_clock);
 
457
}
 
458
 
 
459
/************************************************************************
 
460
Increments the modify clock of a frame by 1. The caller must (1) own the
 
461
buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
 
462
on the block. */
 
463
UNIV_INLINE
 
464
dulint
 
465
buf_block_modify_clock_inc(
 
466
/*=======================*/
 
467
                                /* out: new value */
 
468
        buf_block_t*    block)  /* in: block */
 
469
{
 
470
#ifdef UNIV_SYNC_DEBUG
 
471
        ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0))
 
472
              || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
 
473
#endif /* UNIV_SYNC_DEBUG */
 
474
 
 
475
        UT_DULINT_INC(block->modify_clock);
 
476
 
 
477
        return(block->modify_clock);
 
478
}
 
479
 
 
480
/************************************************************************
 
481
Returns the value of the modify clock. The caller must have an s-lock 
 
482
or x-lock on the block. */
 
483
UNIV_INLINE
 
484
dulint
 
485
buf_block_get_modify_clock(
 
486
/*=======================*/
 
487
                                /* out: value */
 
488
        buf_block_t*    block)  /* in: block */
 
489
{
 
490
#ifdef UNIV_SYNC_DEBUG
 
491
        ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
 
492
              || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
 
493
#endif /* UNIV_SYNC_DEBUG */
 
494
 
 
495
        return(block->modify_clock);
 
496
}
 
497
 
 
498
#ifdef UNIV_SYNC_DEBUG
 
499
/***********************************************************************
 
500
Increments the bufferfix count. */
 
501
UNIV_INLINE
 
502
void
 
503
buf_block_buf_fix_inc_debug(
 
504
/*========================*/
 
505
        buf_block_t*    block,  /* in: block to bufferfix */
 
506
        const char*     file __attribute__ ((unused)),  /* in: file name */
 
507
        ulint           line __attribute__ ((unused)))  /* in: line */
 
508
{
 
509
#ifdef UNIV_SYNC_DEBUG  
 
510
        ibool   ret;
 
511
 
 
512
        ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
 
513
 
 
514
        ut_ad(ret == TRUE);
 
515
        ut_ad(mutex_own(&block->mutex));
 
516
#endif
 
517
        block->buf_fix_count++;
 
518
}
 
519
#else /* UNIV_SYNC_DEBUG */
 
520
/***********************************************************************
 
521
Increments the bufferfix count. */
 
522
UNIV_INLINE
 
523
void
 
524
buf_block_buf_fix_inc(
 
525
/*==================*/
 
526
        buf_block_t*    block)  /* in: block to bufferfix */
 
527
{
 
528
#ifdef UNIV_SYNC_DEBUG
 
529
        ut_ad(mutex_own(&block->mutex));
 
530
#endif
 
531
        block->buf_fix_count++;
 
532
}
 
533
#endif /* UNIV_SYNC_DEBUG */
 
534
/**********************************************************************
 
535
Returns the control block of a file page, NULL if not found. */
 
536
UNIV_INLINE
 
537
buf_block_t*
 
538
buf_page_hash_get(
 
539
/*==============*/
 
540
                        /* out: block, NULL if not found */
 
541
        ulint   space,  /* in: space id */
 
542
        ulint   offset) /* in: offset of the page within space */
 
543
{
 
544
        buf_block_t*    block;
 
545
        ulint           fold;
 
546
        
 
547
        ut_ad(buf_pool);
 
548
#ifdef UNIV_SYNC_DEBUG
 
549
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
550
#endif /* UNIV_SYNC_DEBUG */
 
551
 
 
552
        /* Look for the page in the hash table */
 
553
 
 
554
        fold = buf_page_address_fold(space, offset);
 
555
 
 
556
        HASH_SEARCH(hash, buf_pool->page_hash, fold, block,
 
557
                        (block->space == space) && (block->offset == offset));
 
558
        ut_a(block == NULL || block->state == BUF_BLOCK_FILE_PAGE);
 
559
        
 
560
        return(block);
 
561
}
 
562
 
 
563
/************************************************************************
 
564
Tries to get the page, but if file io is required, releases all latches
 
565
in mtr down to the given savepoint. If io is required, this function
 
566
retrieves the page to buffer buf_pool, but does not bufferfix it or latch
 
567
it. */
 
568
UNIV_INLINE
 
569
buf_frame_t*
 
570
buf_page_get_release_on_io(
 
571
/*=======================*/
 
572
                                /* out: pointer to the frame, or NULL
 
573
                                if not in buffer buf_pool */
 
574
        ulint   space,          /* in: space id */
 
575
        ulint   offset,         /* in: offset of the page within space
 
576
                                in units of a page */
 
577
        buf_frame_t* guess,     /* in: guessed frame or NULL */
 
578
        ulint   rw_latch,       /* in: RW_X_LATCH, RW_S_LATCH,
 
579
                                or RW_NO_LATCH */
 
580
        ulint   savepoint,      /* in: mtr savepoint */
 
581
        mtr_t*  mtr)            /* in: mtr */
 
582
{
 
583
        buf_frame_t*    frame;
 
584
 
 
585
        frame = buf_page_get_gen(space, offset, rw_latch, guess,
 
586
                                BUF_GET_IF_IN_POOL,
 
587
                                __FILE__, __LINE__,
 
588
                                mtr);
 
589
        if (frame != NULL) {
 
590
 
 
591
                return(frame);
 
592
        }
 
593
 
 
594
        /* The page was not in the buffer buf_pool: release the latches
 
595
        down to the savepoint */
 
596
                
 
597
        mtr_rollback_to_savepoint(mtr, savepoint);
 
598
                
 
599
        buf_page_get(space, offset, RW_S_LATCH, mtr);
 
600
                
 
601
        /* When we get here, the page is in buffer, but we release
 
602
        the latches again down to the savepoint, before returning */
 
603
 
 
604
        mtr_rollback_to_savepoint(mtr, savepoint);
 
605
                
 
606
        return(NULL);
 
607
}
 
608
 
 
609
/************************************************************************
 
610
Decrements the bufferfix count of a buffer control block and releases
 
611
a latch, if specified. */
 
612
UNIV_INLINE
 
613
void
 
614
buf_page_release(
 
615
/*=============*/
 
616
        buf_block_t*    block,          /* in: buffer block */
 
617
        ulint           rw_latch,       /* in: RW_S_LATCH, RW_X_LATCH,
 
618
                                        RW_NO_LATCH */
 
619
        mtr_t*          mtr)            /* in: mtr */
 
620
{
 
621
        ulint   buf_fix_count;
 
622
        
 
623
        ut_ad(block);
 
624
 
 
625
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
626
        ut_a(block->buf_fix_count > 0);
 
627
 
 
628
        if (rw_latch == RW_X_LATCH && mtr->modifications) {
 
629
                mutex_enter(&buf_pool->mutex);
 
630
                buf_flush_note_modification(block, mtr);
 
631
                mutex_exit(&buf_pool->mutex);
 
632
        }
 
633
 
 
634
        mutex_enter(&block->mutex);
 
635
 
 
636
#ifdef UNIV_SYNC_DEBUG
 
637
        rw_lock_s_unlock(&(block->debug_latch));
 
638
#endif
 
639
        buf_fix_count = block->buf_fix_count;
 
640
        block->buf_fix_count = buf_fix_count - 1;
 
641
 
 
642
        mutex_exit(&block->mutex);
 
643
 
 
644
        if (rw_latch == RW_S_LATCH) {
 
645
                rw_lock_s_unlock(&(block->lock));
 
646
        } else if (rw_latch == RW_X_LATCH) {
 
647
                rw_lock_x_unlock(&(block->lock));
 
648
        }
 
649
}
 
650
 
 
651
#ifdef UNIV_SYNC_DEBUG
 
652
/*************************************************************************
 
653
Adds latch level info for the rw-lock protecting the buffer frame. This
 
654
should be called in the debug version after a successful latching of a
 
655
page if we know the latching order level of the acquired latch. If
 
656
UNIV_SYNC_DEBUG is not defined, compiles to an empty function. */
 
657
UNIV_INLINE
 
658
void
 
659
buf_page_dbg_add_level(
 
660
/*===================*/
 
661
        buf_frame_t*    frame __attribute__((unused)), /* in: buffer page
 
662
                                where we have acquired latch */
 
663
        ulint           level __attribute__((unused))) /* in: latching order
 
664
                                level */
 
665
{
 
666
        sync_thread_add_level(&(buf_block_align(frame)->lock), level);
 
667
}
 
668
#endif /* UNIV_SYNC_DEBUG */