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 / 1024));
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 + buf_pool->max_size)) {
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. */
98
buf_pool_get_oldest_modification(void)
99
/*==================================*/
100
/* out: oldest modification in pool,
101
ut_dulint_zero if none */
106
mutex_enter(&(buf_pool->mutex));
108
block = UT_LIST_GET_LAST(buf_pool->flush_list);
111
lsn = ut_dulint_zero;
113
lsn = block->oldest_modification;
116
mutex_exit(&(buf_pool->mutex));
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! */
126
buf_pool_clock_tic(void)
127
/*====================*/
128
/* out: new clock value */
130
#ifdef UNIV_SYNC_DEBUG
131
ut_ad(mutex_own(&(buf_pool->mutex)));
132
#endif /* UNIV_SYNC_DEBUG */
134
buf_pool->ulint_clock++;
136
return(buf_pool->ulint_clock);
139
/*************************************************************************
140
Gets a pointer to the memory frame of a block. */
145
/* out: pointer to the frame */
146
buf_block_t* block) /* in: pointer to the control 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));
155
return(block->frame);
158
/*************************************************************************
159
Gets the space id of a block. */
165
buf_block_t* block) /* in: pointer to the control 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);
173
return(block->space);
176
/*************************************************************************
177
Gets the page number of a block. */
180
buf_block_get_page_no(
181
/*==================*/
182
/* out: page number */
183
buf_block_t* block) /* in: pointer to the control 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);
191
return(block->offset);
194
/***********************************************************************
195
Gets the block to whose frame the pointer is pointing to. */
200
/* out: pointer to block */
201
byte* ptr) /* in: pointer to a frame */
204
buf_frame_t* frame_zero;
208
frame_zero = buf_pool->frame_zero;
210
if (UNIV_UNLIKELY((ulint)ptr < (ulint)frame_zero)
211
|| UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) {
213
ut_print_timestamp(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",
226
block = *(buf_pool->blocks_of_frames + (((ulint)(ptr - frame_zero))
227
>> UNIV_PAGE_SIZE_SHIFT));
231
/***********************************************************************
232
Gets the frame the pointer is pointing to. */
237
/* out: pointer to frame */
238
byte* ptr) /* in: pointer to a frame */
244
frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
246
if (UNIV_UNLIKELY((ulint)frame < (ulint)(buf_pool->frame_zero))
247
|| UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) {
249
ut_print_timestamp(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,
265
/**************************************************************************
266
Gets the page number of a pointer pointing within a buffer frame containing
270
buf_frame_get_page_no(
271
/*==================*/
272
/* out: page number */
273
byte* ptr) /* in: pointer to within a buffer frame */
275
return(buf_block_get_page_no(buf_block_align(ptr)));
278
/**************************************************************************
279
Gets the space id of a pointer pointing within a buffer frame containing a
283
buf_frame_get_space_id(
284
/*===================*/
286
byte* ptr) /* in: pointer to within a buffer frame */
288
return(buf_block_get_space(buf_block_align(ptr)));
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. */
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 */
304
block = buf_block_align(ptr);
306
*space = buf_block_get_space(block);
307
addr->page = buf_block_get_page_no(block);
308
addr->boffset = ptr - buf_frame_align(ptr);
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. */
316
buf_frame_get_lock_hash_val(
317
/*========================*/
318
/* out: lock hash value */
319
byte* ptr) /* in: pointer to within a buffer frame */
323
block = buf_block_align(ptr);
325
return(block->lock_hash_val);
328
/**************************************************************************
329
Gets the mutex number protecting the page record lock hash chain in the lock
336
byte* ptr) /* in: pointer to within a buffer frame */
340
block = buf_block_align(ptr);
342
return(&block->mutex);
345
/*************************************************************************
346
Copies contents of a buffer frame to a given buffer. */
352
byte* buf, /* in: buffer to copy to */
353
buf_frame_t* frame) /* in: buffer frame */
357
ut_memcpy(buf, frame, UNIV_PAGE_SIZE);
362
/************************************************************************
363
Calculates a folded value of a file page address to use in the page hash
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 */
373
return((space << 20) + space + offset);
376
/************************************************************************
377
This function is used to get info if there is an io operation
378
going on on a buffer page. */
383
/* out: TRUE if io going on */
384
buf_block_t* block) /* in: buf_pool block, must be bufferfixed */
386
mutex_enter(&(buf_pool->mutex));
388
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
389
ut_ad(block->buf_fix_count > 0);
391
if (block->io_fix != 0) {
392
mutex_exit(&(buf_pool->mutex));
397
mutex_exit(&(buf_pool->mutex));
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. */
407
buf_frame_get_newest_modification(
408
/*==============================*/
409
/* out: newest modification to the page */
410
buf_frame_t* frame) /* in: pointer to a frame */
417
block = buf_block_align(frame);
419
mutex_enter(&(buf_pool->mutex));
421
if (block->state == BUF_BLOCK_FILE_PAGE) {
422
lsn = block->newest_modification;
424
lsn = ut_dulint_zero;
427
mutex_exit(&(buf_pool->mutex));
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
438
buf_frame_modify_clock_inc(
439
/*=======================*/
441
buf_frame_t* frame) /* in: pointer to a frame */
447
block = buf_block_align(frame);
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 */
454
UT_DULINT_INC(block->modify_clock);
456
return(block->modify_clock);
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
465
buf_block_modify_clock_inc(
466
/*=======================*/
468
buf_block_t* block) /* in: block */
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 */
475
UT_DULINT_INC(block->modify_clock);
477
return(block->modify_clock);
480
/************************************************************************
481
Returns the value of the modify clock. The caller must have an s-lock
482
or x-lock on the block. */
485
buf_block_get_modify_clock(
486
/*=======================*/
488
buf_block_t* block) /* in: block */
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 */
495
return(block->modify_clock);
498
#ifdef UNIV_SYNC_DEBUG
499
/***********************************************************************
500
Increments the bufferfix count. */
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 */
509
#ifdef UNIV_SYNC_DEBUG
512
ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
515
ut_ad(mutex_own(&block->mutex));
517
block->buf_fix_count++;
519
#else /* UNIV_SYNC_DEBUG */
520
/***********************************************************************
521
Increments the bufferfix count. */
524
buf_block_buf_fix_inc(
525
/*==================*/
526
buf_block_t* block) /* in: block to bufferfix */
528
#ifdef UNIV_SYNC_DEBUG
529
ut_ad(mutex_own(&block->mutex));
531
block->buf_fix_count++;
533
#endif /* UNIV_SYNC_DEBUG */
534
/**********************************************************************
535
Returns the control block of a file page, NULL if not found. */
540
/* out: block, NULL if not found */
541
ulint space, /* in: space id */
542
ulint offset) /* in: offset of the page within space */
548
#ifdef UNIV_SYNC_DEBUG
549
ut_ad(mutex_own(&(buf_pool->mutex)));
550
#endif /* UNIV_SYNC_DEBUG */
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 */
625
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
626
ut_a(block->buf_fix_count > 0);
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);
634
mutex_enter(&block->mutex);
636
#ifdef UNIV_SYNC_DEBUG
637
rw_lock_s_unlock(&(block->debug_latch));
639
buf_fix_count = block->buf_fix_count;
640
block->buf_fix_count = buf_fix_count - 1;
642
mutex_exit(&block->mutex);
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));
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. */
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
666
sync_thread_add_level(&(buf_block_align(frame)->lock), level);
668
#endif /* UNIV_SYNC_DEBUG */