~linuxjedi/drizzle/trunk-bug-667053

« back to all changes in this revision

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

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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 / 4));
 
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
 
86
                + buf_pool->max_size)) {
 
87
 
 
88
                return(TRUE);
 
89
        }
 
90
 
 
91
        return(FALSE);
 
92
}
 
93
 
 
94
/************************************************************************
 
95
Gets the smallest oldest_modification lsn for any page in the pool. Returns
 
96
ut_dulint_zero if all modified pages have been flushed to disk. */
 
97
UNIV_INLINE
 
98
dulint
 
99
buf_pool_get_oldest_modification(void)
 
100
/*==================================*/
 
101
                                /* out: oldest modification in pool,
 
102
                                ut_dulint_zero if none */
 
103
{
 
104
        buf_block_t*    block;
 
105
        dulint          lsn;
 
106
 
 
107
        mutex_enter(&(buf_pool->mutex));
 
108
 
 
109
        block = UT_LIST_GET_LAST(buf_pool->flush_list);
 
110
 
 
111
        if (block == NULL) {
 
112
                lsn = ut_dulint_zero;
 
113
        } else {
 
114
                lsn = block->oldest_modification;
 
115
        }
 
116
 
 
117
        mutex_exit(&(buf_pool->mutex));
 
118
 
 
119
        return(lsn);
 
120
}
 
121
 
 
122
/***********************************************************************
 
123
Increments the buf_pool clock by one and returns its new value. Remember
 
124
that in the 32 bit version the clock wraps around at 4 billion! */
 
125
UNIV_INLINE
 
126
ulint
 
127
buf_pool_clock_tic(void)
 
128
/*====================*/
 
129
                        /* out: new clock value */
 
130
{
 
131
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
132
 
 
133
        buf_pool->ulint_clock++;
 
134
 
 
135
        return(buf_pool->ulint_clock);
 
136
}
 
137
 
 
138
/*************************************************************************
 
139
Gets a pointer to the memory frame of a block. */
 
140
UNIV_INLINE
 
141
buf_frame_t*
 
142
buf_block_get_frame(
 
143
/*================*/
 
144
                                /* out: pointer to the frame */
 
145
        buf_block_t*    block)  /* in: pointer to the control block */
 
146
{
 
147
        ut_ad(block);
 
148
        ut_ad(block >= buf_pool->blocks);
 
149
        ut_ad(block < buf_pool->blocks + buf_pool->max_size);
 
150
        ut_ad(block->state != BUF_BLOCK_NOT_USED);
 
151
        ut_ad((block->state != BUF_BLOCK_FILE_PAGE)
 
152
              || (block->buf_fix_count > 0));
 
153
 
 
154
        return(block->frame);
 
155
}
 
156
 
 
157
/*************************************************************************
 
158
Gets the space id of a block. */
 
159
UNIV_INLINE
 
160
ulint
 
161
buf_block_get_space(
 
162
/*================*/
 
163
                                /* out: space id */
 
164
        buf_block_t*    block)  /* in: pointer to the control block */
 
165
{
 
166
        ut_ad(block);
 
167
        ut_ad(block >= buf_pool->blocks);
 
168
        ut_ad(block < buf_pool->blocks + buf_pool->max_size);
 
169
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
170
        ut_ad(block->buf_fix_count > 0);
 
171
 
 
172
        return(block->space);
 
173
}
 
174
 
 
175
/*************************************************************************
 
176
Gets the page number of a block. */
 
177
UNIV_INLINE
 
178
ulint
 
179
buf_block_get_page_no(
 
180
/*==================*/
 
181
                                /* out: page number */
 
182
        buf_block_t*    block)  /* in: pointer to the control block */
 
183
{
 
184
        ut_ad(block);
 
185
        ut_ad(block >= buf_pool->blocks);
 
186
        ut_ad(block < buf_pool->blocks + buf_pool->max_size);
 
187
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
188
        ut_ad(block->buf_fix_count > 0);
 
189
 
 
190
        return(block->offset);
 
191
}
 
192
 
 
193
/***********************************************************************
 
194
Gets the block to whose frame the pointer is pointing to. */
 
195
UNIV_INLINE
 
196
buf_block_t*
 
197
buf_block_align(
 
198
/*============*/
 
199
                        /* out: pointer to block */
 
200
        byte*   ptr)    /* in: pointer to a frame */
 
201
{
 
202
        buf_block_t*    block;
 
203
        buf_frame_t*    frame_zero;
 
204
 
 
205
        ut_ad(ptr);
 
206
 
 
207
        frame_zero = buf_pool->frame_zero;
 
208
 
 
209
        if (UNIV_UNLIKELY((ulint)ptr < (ulint)frame_zero)
 
210
            || UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) {
 
211
 
 
212
                ut_print_timestamp(stderr);
 
213
                fprintf(stderr,
 
214
                        "InnoDB: Error: trying to access a stray pointer %p\n"
 
215
                        "InnoDB: buf pool start is at %p, end at %p\n"
 
216
                        "InnoDB: Probable reason is database corruption"
 
217
                        " or memory\n"
 
218
                        "InnoDB: corruption. If this happens in an"
 
219
                        " InnoDB database recovery, see\n"
 
220
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
 
221
                        "forcing-recovery.html\n"
 
222
                        "InnoDB: how to force recovery.\n",
 
223
                        ptr, frame_zero,
 
224
                        buf_pool->high_end);
 
225
                ut_error;
 
226
        }
 
227
 
 
228
        block = *(buf_pool->blocks_of_frames + (((ulint)(ptr - frame_zero))
 
229
                                                >> UNIV_PAGE_SIZE_SHIFT));
 
230
        return(block);
 
231
}
 
232
 
 
233
/***********************************************************************
 
234
Gets the frame the pointer is pointing to. */
 
235
UNIV_INLINE
 
236
buf_frame_t*
 
237
buf_frame_align(
 
238
/*============*/
 
239
                        /* out: pointer to frame */
 
240
        byte*   ptr)    /* in: pointer to a frame */
 
241
{
 
242
        buf_frame_t*    frame;
 
243
 
 
244
        ut_ad(ptr);
 
245
 
 
246
        frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
 
247
 
 
248
        if (UNIV_UNLIKELY((ulint)frame < (ulint)(buf_pool->frame_zero))
 
249
            || UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) {
 
250
 
 
251
                ut_print_timestamp(stderr);
 
252
                fprintf(stderr,
 
253
                        "InnoDB: Error: trying to access a stray pointer %p\n"
 
254
                        "InnoDB: buf pool start is at %p, end at %p\n"
 
255
                        "InnoDB: Probable reason is database corruption"
 
256
                        " or memory\n"
 
257
                        "InnoDB: corruption. If this happens in an"
 
258
                        " InnoDB database recovery, see\n"
 
259
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
 
260
                        "forcing-recovery.html\n"
 
261
                        "InnoDB: how to force recovery.\n",
 
262
                        ptr, buf_pool->frame_zero,
 
263
                        buf_pool->high_end);
 
264
                ut_error;
 
265
        }
 
266
 
 
267
        return(frame);
 
268
}
 
269
 
 
270
/**************************************************************************
 
271
Gets the page number of a pointer pointing within a buffer frame containing
 
272
a file page. */
 
273
UNIV_INLINE
 
274
ulint
 
275
buf_frame_get_page_no(
 
276
/*==================*/
 
277
                        /* out: page number */
 
278
        byte*   ptr)    /* in: pointer to within a buffer frame */
 
279
{
 
280
        return(buf_block_get_page_no(buf_block_align(ptr)));
 
281
}
 
282
 
 
283
/**************************************************************************
 
284
Gets the space id of a pointer pointing within a buffer frame containing a
 
285
file page. */
 
286
UNIV_INLINE
 
287
ulint
 
288
buf_frame_get_space_id(
 
289
/*===================*/
 
290
                        /* out: space id */
 
291
        byte*   ptr)    /* in: pointer to within a buffer frame */
 
292
{
 
293
        return(buf_block_get_space(buf_block_align(ptr)));
 
294
}
 
295
 
 
296
/**************************************************************************
 
297
Gets the space id, page offset, and byte offset within page of a
 
298
pointer pointing to a buffer frame containing a file page. */
 
299
UNIV_INLINE
 
300
void
 
301
buf_ptr_get_fsp_addr(
 
302
/*=================*/
 
303
        byte*           ptr,    /* in: pointer to a buffer frame */
 
304
        ulint*          space,  /* out: space id */
 
305
        fil_addr_t*     addr)   /* out: page offset and byte offset */
 
306
{
 
307
        buf_block_t*    block;
 
308
 
 
309
        block = buf_block_align(ptr);
 
310
 
 
311
        *space = buf_block_get_space(block);
 
312
        addr->page = buf_block_get_page_no(block);
 
313
        addr->boffset = ptr - buf_frame_align(ptr);
 
314
}
 
315
 
 
316
/**************************************************************************
 
317
Gets the hash value of the page the pointer is pointing to. This can be used
 
318
in searches in the lock hash table. */
 
319
UNIV_INLINE
 
320
ulint
 
321
buf_frame_get_lock_hash_val(
 
322
/*========================*/
 
323
                        /* out: lock hash value */
 
324
        byte*   ptr)    /* in: pointer to within a buffer frame */
 
325
{
 
326
        buf_block_t*    block;
 
327
 
 
328
        block = buf_block_align(ptr);
 
329
 
 
330
        return(block->lock_hash_val);
 
331
}
 
332
 
 
333
/**************************************************************************
 
334
Gets the mutex number protecting the page record lock hash chain in the lock
 
335
table. */
 
336
UNIV_INLINE
 
337
mutex_t*
 
338
buf_frame_get_mutex(
 
339
/*================*/
 
340
                        /* out: mutex */
 
341
        byte*   ptr)    /* in: pointer to within a buffer frame */
 
342
{
 
343
        buf_block_t*    block;
 
344
 
 
345
        block = buf_block_align(ptr);
 
346
 
 
347
        return(&block->mutex);
 
348
}
 
349
 
 
350
/*************************************************************************
 
351
Copies contents of a buffer frame to a given buffer. */
 
352
UNIV_INLINE
 
353
byte*
 
354
buf_frame_copy(
 
355
/*===========*/
 
356
                                /* out: buf */
 
357
        byte*           buf,    /* in: buffer to copy to */
 
358
        buf_frame_t*    frame)  /* in: buffer frame */
 
359
{
 
360
        ut_ad(buf && frame);
 
361
 
 
362
        ut_memcpy(buf, frame, UNIV_PAGE_SIZE);
 
363
 
 
364
        return(buf);
 
365
}
 
366
 
 
367
/************************************************************************
 
368
Calculates a folded value of a file page address to use in the page hash
 
369
table. */
 
370
UNIV_INLINE
 
371
ulint
 
372
buf_page_address_fold(
 
373
/*==================*/
 
374
                        /* out: the folded value */
 
375
        ulint   space,  /* in: space id */
 
376
        ulint   offset) /* in: offset of the page within space */
 
377
{
 
378
        return((space << 20) + space + offset);
 
379
}
 
380
 
 
381
/************************************************************************
 
382
This function is used to get info if there is an io operation
 
383
going on on a buffer page. */
 
384
UNIV_INLINE
 
385
ibool
 
386
buf_page_io_query(
 
387
/*==============*/
 
388
                                /* out: TRUE if io going on */
 
389
        buf_block_t*    block)  /* in: buf_pool block, must be bufferfixed */
 
390
{
 
391
        mutex_enter(&(buf_pool->mutex));
 
392
 
 
393
        ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
 
394
        ut_ad(block->buf_fix_count > 0);
 
395
 
 
396
        if (block->io_fix != 0) {
 
397
                mutex_exit(&(buf_pool->mutex));
 
398
 
 
399
                return(TRUE);
 
400
        }
 
401
 
 
402
        mutex_exit(&(buf_pool->mutex));
 
403
 
 
404
        return(FALSE);
 
405
}
 
406
 
 
407
/************************************************************************
 
408
Gets the youngest modification log sequence number for a frame. Returns zero
 
409
if not a file page or no modification occurred yet. */
 
410
UNIV_INLINE
 
411
dulint
 
412
buf_frame_get_newest_modification(
 
413
/*==============================*/
 
414
                                /* out: newest modification to the page */
 
415
        buf_frame_t*    frame)  /* in: pointer to a frame */
 
416
{
 
417
        buf_block_t*    block;
 
418
        dulint          lsn;
 
419
 
 
420
        ut_ad(frame);
 
421
 
 
422
        block = buf_block_align(frame);
 
423
 
 
424
        mutex_enter(&(buf_pool->mutex));
 
425
 
 
426
        if (block->state == BUF_BLOCK_FILE_PAGE) {
 
427
                lsn = block->newest_modification;
 
428
        } else {
 
429
                lsn = ut_dulint_zero;
 
430
        }
 
431
 
 
432
        mutex_exit(&(buf_pool->mutex));
 
433
 
 
434
        return(lsn);
 
435
}
 
436
 
 
437
/************************************************************************
 
438
Increments the modify clock of a frame by 1. The caller must (1) own the
 
439
buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
 
440
on the block. */
 
441
UNIV_INLINE
 
442
dulint
 
443
buf_frame_modify_clock_inc(
 
444
/*=======================*/
 
445
                                /* out: new value */
 
446
        buf_frame_t*    frame)  /* in: pointer to a frame */
 
447
{
 
448
        buf_block_t*    block;
 
449
 
 
450
        ut_ad(frame);
 
451
 
 
452
        block = buf_block_align(frame);
 
453
 
 
454
#ifdef UNIV_SYNC_DEBUG
 
455
        ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0))
 
456
              || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
 
457
#endif /* UNIV_SYNC_DEBUG */
 
458
 
 
459
        UT_DULINT_INC(block->modify_clock);
 
460
 
 
461
        return(block->modify_clock);
 
462
}
 
463
 
 
464
/************************************************************************
 
465
Increments the modify clock of a frame by 1. The caller must (1) own the
 
466
buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
 
467
on the block. */
 
468
UNIV_INLINE
 
469
dulint
 
470
buf_block_modify_clock_inc(
 
471
/*=======================*/
 
472
                                /* out: new value */
 
473
        buf_block_t*    block)  /* in: block */
 
474
{
 
475
#ifdef UNIV_SYNC_DEBUG
 
476
        ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0))
 
477
              || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
 
478
#endif /* UNIV_SYNC_DEBUG */
 
479
 
 
480
        UT_DULINT_INC(block->modify_clock);
 
481
 
 
482
        return(block->modify_clock);
 
483
}
 
484
 
 
485
/************************************************************************
 
486
Returns the value of the modify clock. The caller must have an s-lock
 
487
or x-lock on the block. */
 
488
UNIV_INLINE
 
489
dulint
 
490
buf_block_get_modify_clock(
 
491
/*=======================*/
 
492
                                /* out: value */
 
493
        buf_block_t*    block)  /* in: block */
 
494
{
 
495
#ifdef UNIV_SYNC_DEBUG
 
496
        ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
 
497
              || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
 
498
#endif /* UNIV_SYNC_DEBUG */
 
499
 
 
500
        return(block->modify_clock);
 
501
}
 
502
 
 
503
#ifdef UNIV_SYNC_DEBUG
 
504
/***********************************************************************
 
505
Increments the bufferfix count. */
 
506
UNIV_INLINE
 
507
void
 
508
buf_block_buf_fix_inc_debug(
 
509
/*========================*/
 
510
        buf_block_t*    block,  /* in: block to bufferfix */
 
511
        const char*     file __attribute__ ((unused)),  /* in: file name */
 
512
        ulint           line __attribute__ ((unused)))  /* in: line */
 
513
{
 
514
        ibool   ret;
 
515
 
 
516
        ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
 
517
 
 
518
        ut_ad(ret == TRUE);
 
519
        ut_ad(mutex_own(&block->mutex));
 
520
        block->buf_fix_count++;
 
521
}
 
522
#else /* UNIV_SYNC_DEBUG */
 
523
/***********************************************************************
 
524
Increments the bufferfix count. */
 
525
UNIV_INLINE
 
526
void
 
527
buf_block_buf_fix_inc(
 
528
/*==================*/
 
529
        buf_block_t*    block)  /* in: block to bufferfix */
 
530
{
 
531
        ut_ad(mutex_own(&block->mutex));
 
532
 
 
533
        block->buf_fix_count++;
 
534
}
 
535
#endif /* UNIV_SYNC_DEBUG */
 
536
/**********************************************************************
 
537
Returns the control block of a file page, NULL if not found. */
 
538
UNIV_INLINE
 
539
buf_block_t*
 
540
buf_page_hash_get(
 
541
/*==============*/
 
542
                        /* out: block, NULL if not found */
 
543
        ulint   space,  /* in: space id */
 
544
        ulint   offset) /* in: offset of the page within space */
 
545
{
 
546
        buf_block_t*    block;
 
547
        ulint           fold;
 
548
 
 
549
        ut_ad(buf_pool);
 
550
        ut_ad(mutex_own(&(buf_pool->mutex)));
 
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
        ut_ad(block);
 
622
 
 
623
        ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
624
        ut_a(block->buf_fix_count > 0);
 
625
 
 
626
        if (rw_latch == RW_X_LATCH && mtr->modifications) {
 
627
                mutex_enter(&buf_pool->mutex);
 
628
                buf_flush_note_modification(block, mtr);
 
629
                mutex_exit(&buf_pool->mutex);
 
630
        }
 
631
 
 
632
        mutex_enter(&block->mutex);
 
633
 
 
634
#ifdef UNIV_SYNC_DEBUG
 
635
        rw_lock_s_unlock(&(block->debug_latch));
 
636
#endif
 
637
        block->buf_fix_count--;
 
638
 
 
639
        mutex_exit(&block->mutex);
 
640
 
 
641
        if (rw_latch == RW_S_LATCH) {
 
642
                rw_lock_s_unlock(&(block->lock));
 
643
        } else if (rw_latch == RW_X_LATCH) {
 
644
                rw_lock_x_unlock(&(block->lock));
 
645
        }
 
646
}
 
647
 
 
648
#ifdef UNIV_SYNC_DEBUG
 
649
/*************************************************************************
 
650
Adds latch level info for the rw-lock protecting the buffer frame. This
 
651
should be called in the debug version after a successful latching of a
 
652
page if we know the latching order level of the acquired latch. If
 
653
UNIV_SYNC_DEBUG is not defined, compiles to an empty function. */
 
654
UNIV_INLINE
 
655
void
 
656
buf_page_dbg_add_level(
 
657
/*===================*/
 
658
        buf_frame_t*    frame __attribute__((unused)), /* in: buffer page
 
659
                                where we have acquired latch */
 
660
        ulint           level __attribute__((unused))) /* in: latching order
 
661
                                level */
 
662
{
 
663
        sync_thread_add_level(&(buf_block_align(frame)->lock), level);
 
664
}
 
665
#endif /* UNIV_SYNC_DEBUG */