1
/******************************************************
2
The database buffer buf_pool
6
Created 11/5/1995 Heikki Tuuri
7
*******************************************************/
15
extern ulint buf_dbg_counter; /* This is used to insert validation
16
operations in execution in the
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
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 */
30
return(buf_pool->freed_page_clock >= block->freed_page_clock
31
+ 1 + (buf_pool->curr_size / 4));
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). */
39
buf_pool_get_curr_size(void)
40
/*========================*/
41
/* out: size in bytes */
43
return((buf_pool->n_frames) * UNIV_PAGE_SIZE);
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). */
51
buf_pool_get_max_size(void)
52
/*=======================*/
53
/* out: size in bytes */
55
return((buf_pool->n_frames) * UNIV_PAGE_SIZE);
58
/***********************************************************************
59
Accessor function for block array. */
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 */
69
ut_ad(i < buf_pool->max_size);
71
return(i + buf_pool->blocks);
74
/***********************************************************************
75
Checks if a pointer points to the block array of the buffer pool (blocks, not
81
/* out: TRUE if pointer to block */
82
void* ptr) /* in: pointer to memory */
84
if ((buf_pool->blocks <= (buf_block_t*)ptr)
85
&& ((buf_block_t*)ptr < buf_pool->blocks
86
+ buf_pool->max_size)) {
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. */
99
buf_pool_get_oldest_modification(void)
100
/*==================================*/
101
/* out: oldest modification in pool,
102
ut_dulint_zero if none */
107
mutex_enter(&(buf_pool->mutex));
109
block = UT_LIST_GET_LAST(buf_pool->flush_list);
112
lsn = ut_dulint_zero;
114
lsn = block->oldest_modification;
117
mutex_exit(&(buf_pool->mutex));
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! */
127
buf_pool_clock_tic(void)
128
/*====================*/
129
/* out: new clock value */
131
ut_ad(mutex_own(&(buf_pool->mutex)));
133
buf_pool->ulint_clock++;
135
return(buf_pool->ulint_clock);
138
/*************************************************************************
139
Gets a pointer to the memory frame of a block. */
144
/* out: pointer to the frame */
145
buf_block_t* block) /* in: pointer to the control 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));
154
return(block->frame);
157
/*************************************************************************
158
Gets the space id of a block. */
164
buf_block_t* block) /* in: pointer to the control 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);
172
return(block->space);
175
/*************************************************************************
176
Gets the page number of a block. */
179
buf_block_get_page_no(
180
/*==================*/
181
/* out: page number */
182
buf_block_t* block) /* in: pointer to the control 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);
190
return(block->offset);
193
/***********************************************************************
194
Gets the block to whose frame the pointer is pointing to. */
199
/* out: pointer to block */
200
byte* ptr) /* in: pointer to a frame */
203
buf_frame_t* frame_zero;
207
frame_zero = buf_pool->frame_zero;
209
if (UNIV_UNLIKELY((ulint)ptr < (ulint)frame_zero)
210
|| UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) {
212
ut_print_timestamp(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"
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",
228
block = *(buf_pool->blocks_of_frames + (((ulint)(ptr - frame_zero))
229
>> UNIV_PAGE_SIZE_SHIFT));
233
/***********************************************************************
234
Gets the frame the pointer is pointing to. */
239
/* out: pointer to frame */
240
byte* ptr) /* in: pointer to a frame */
246
frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
248
if (UNIV_UNLIKELY((ulint)frame < (ulint)(buf_pool->frame_zero))
249
|| UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) {
251
ut_print_timestamp(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"
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,
270
/**************************************************************************
271
Gets the page number of a pointer pointing within a buffer frame containing
275
buf_frame_get_page_no(
276
/*==================*/
277
/* out: page number */
278
byte* ptr) /* in: pointer to within a buffer frame */
280
return(buf_block_get_page_no(buf_block_align(ptr)));
283
/**************************************************************************
284
Gets the space id of a pointer pointing within a buffer frame containing a
288
buf_frame_get_space_id(
289
/*===================*/
291
byte* ptr) /* in: pointer to within a buffer frame */
293
return(buf_block_get_space(buf_block_align(ptr)));
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. */
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 */
309
block = buf_block_align(ptr);
311
*space = buf_block_get_space(block);
312
addr->page = buf_block_get_page_no(block);
313
addr->boffset = ptr - buf_frame_align(ptr);
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. */
321
buf_frame_get_lock_hash_val(
322
/*========================*/
323
/* out: lock hash value */
324
byte* ptr) /* in: pointer to within a buffer frame */
328
block = buf_block_align(ptr);
330
return(block->lock_hash_val);
333
/**************************************************************************
334
Gets the mutex number protecting the page record lock hash chain in the lock
341
byte* ptr) /* in: pointer to within a buffer frame */
345
block = buf_block_align(ptr);
347
return(&block->mutex);
350
/*************************************************************************
351
Copies contents of a buffer frame to a given buffer. */
357
byte* buf, /* in: buffer to copy to */
358
buf_frame_t* frame) /* in: buffer frame */
362
ut_memcpy(buf, frame, UNIV_PAGE_SIZE);
367
/************************************************************************
368
Calculates a folded value of a file page address to use in the page hash
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 */
378
return((space << 20) + space + offset);
381
/************************************************************************
382
This function is used to get info if there is an io operation
383
going on on a buffer page. */
388
/* out: TRUE if io going on */
389
buf_block_t* block) /* in: buf_pool block, must be bufferfixed */
391
mutex_enter(&(buf_pool->mutex));
393
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
394
ut_ad(block->buf_fix_count > 0);
396
if (block->io_fix != 0) {
397
mutex_exit(&(buf_pool->mutex));
402
mutex_exit(&(buf_pool->mutex));
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. */
412
buf_frame_get_newest_modification(
413
/*==============================*/
414
/* out: newest modification to the page */
415
buf_frame_t* frame) /* in: pointer to a frame */
422
block = buf_block_align(frame);
424
mutex_enter(&(buf_pool->mutex));
426
if (block->state == BUF_BLOCK_FILE_PAGE) {
427
lsn = block->newest_modification;
429
lsn = ut_dulint_zero;
432
mutex_exit(&(buf_pool->mutex));
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
443
buf_frame_modify_clock_inc(
444
/*=======================*/
446
buf_frame_t* frame) /* in: pointer to a frame */
452
block = buf_block_align(frame);
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 */
459
UT_DULINT_INC(block->modify_clock);
461
return(block->modify_clock);
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
470
buf_block_modify_clock_inc(
471
/*=======================*/
473
buf_block_t* block) /* in: block */
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 */
480
UT_DULINT_INC(block->modify_clock);
482
return(block->modify_clock);
485
/************************************************************************
486
Returns the value of the modify clock. The caller must have an s-lock
487
or x-lock on the block. */
490
buf_block_get_modify_clock(
491
/*=======================*/
493
buf_block_t* block) /* in: block */
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 */
500
return(block->modify_clock);
503
#ifdef UNIV_SYNC_DEBUG
504
/***********************************************************************
505
Increments the bufferfix count. */
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 */
516
ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
519
ut_ad(mutex_own(&block->mutex));
520
block->buf_fix_count++;
522
#else /* UNIV_SYNC_DEBUG */
523
/***********************************************************************
524
Increments the bufferfix count. */
527
buf_block_buf_fix_inc(
528
/*==================*/
529
buf_block_t* block) /* in: block to bufferfix */
531
ut_ad(mutex_own(&block->mutex));
533
block->buf_fix_count++;
535
#endif /* UNIV_SYNC_DEBUG */
536
/**********************************************************************
537
Returns the control block of a file page, NULL if not found. */
542
/* out: block, NULL if not found */
543
ulint space, /* in: space id */
544
ulint offset) /* in: offset of the page within space */
550
ut_ad(mutex_own(&(buf_pool->mutex)));
552
/* Look for the page in the hash table */
554
fold = buf_page_address_fold(space, offset);
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);
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
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,
580
ulint savepoint, /* in: mtr savepoint */
581
mtr_t* mtr) /* in: mtr */
585
frame = buf_page_get_gen(space, offset, rw_latch, guess,
594
/* The page was not in the buffer buf_pool: release the latches
595
down to the savepoint */
597
mtr_rollback_to_savepoint(mtr, savepoint);
599
buf_page_get(space, offset, RW_S_LATCH, mtr);
601
/* When we get here, the page is in buffer, but we release
602
the latches again down to the savepoint, before returning */
604
mtr_rollback_to_savepoint(mtr, savepoint);
609
/************************************************************************
610
Decrements the bufferfix count of a buffer control block and releases
611
a latch, if specified. */
616
buf_block_t* block, /* in: buffer block */
617
ulint rw_latch, /* in: RW_S_LATCH, RW_X_LATCH,
619
mtr_t* mtr) /* in: mtr */
623
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
624
ut_a(block->buf_fix_count > 0);
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);
632
mutex_enter(&block->mutex);
634
#ifdef UNIV_SYNC_DEBUG
635
rw_lock_s_unlock(&(block->debug_latch));
637
block->buf_fix_count--;
639
mutex_exit(&block->mutex);
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));
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. */
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
663
sync_thread_add_level(&(buf_block_align(frame)->lock), level);
665
#endif /* UNIV_SYNC_DEBUG */