#include "buf0flu.h"#include "ut0byte.h"#include "ut0lst.h"#include "page0page.h"#include "fil0fil.h"#include "buf0buf.h"#include "buf0lru.h"#include "buf0rea.h"#include "ibuf0ibuf.h"#include "log0log.h"#include "os0file.h"#include "trx0sys.h"#include "srv0srv.h"Include dependency graph for buf0flu.c:

Go to the source code of this file.
| #define BUF_FLUSH_AREA |
Value:
ut_min(BUF_READ_AHEAD_AREA,\ buf_pool->curr_size / 16)
Definition at line 32 of file buf0flu.c.
Referenced by buf_flush_try_neighbors().
Definition at line 785 of file buf0flu.c.
References yaSSL::block, BUF_BLOCK_FILE_PAGE, buf_flush_buffered_writes(), BUF_FLUSH_LIST, BUF_FLUSH_LRU, buf_flush_ready_for_flush(), buf_flush_try_neighbors(), buf_pool, FALSE, buf_pool_struct::init_flush, buf_pool_struct::mutex, mutex_enter, mutex_exit(), buf_pool_struct::n_flush, buf_pool_struct::no_flush, NULL, offset, os_event_set(), srv_buf_pool_flushed, sync_thread_levels_empty_gen(), TRUE, ut_a, ut_ad, ut_dulint_cmp(), UT_LIST_GET_LAST, and UT_LIST_GET_PREV.
Referenced by buf_flush_free_margin(), log_preflush_pool_modified_pages(), recv_apply_hashed_log_recs(), and srv_master_thread().
00787 : number of blocks for which the write 00788 request was queued; ULINT_UNDEFINED if there 00789 was a flush of the same type already running */ 00790 ulint flush_type, /* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST; if 00791 BUF_FLUSH_LIST, then the caller must not own 00792 any latches on pages */ 00793 ulint min_n, /* in: wished minimum mumber of blocks flushed 00794 (it is not guaranteed that the actual number 00795 is that big, though) */ 00796 dulint lsn_limit) /* in the case BUF_FLUSH_LIST all blocks whose 00797 oldest_modification is smaller than this 00798 should be flushed (if their number does not 00799 exceed min_n), otherwise ignored */ 00800 { 00801 buf_block_t* block; 00802 ulint page_count = 0; 00803 ulint old_page_count; 00804 ulint space; 00805 ulint offset; 00806 ibool found; 00807 00808 ut_ad((flush_type == BUF_FLUSH_LRU) 00809 || (flush_type == BUF_FLUSH_LIST)); 00810 ut_ad((flush_type != BUF_FLUSH_LIST) 00811 || sync_thread_levels_empty_gen(TRUE)); 00812 mutex_enter(&(buf_pool->mutex)); 00813 00814 if ((buf_pool->n_flush[flush_type] > 0) 00815 || (buf_pool->init_flush[flush_type] == TRUE)) { 00816 00817 /* There is already a flush batch of the same type running */ 00818 00819 mutex_exit(&(buf_pool->mutex)); 00820 00821 return(ULINT_UNDEFINED); 00822 } 00823 00824 (buf_pool->init_flush)[flush_type] = TRUE; 00825 00826 for (;;) { 00827 /* If we have flushed enough, leave the loop */ 00828 if (page_count >= min_n) { 00829 00830 break; 00831 } 00832 00833 /* Start from the end of the list looking for a suitable 00834 block to be flushed. */ 00835 00836 if (flush_type == BUF_FLUSH_LRU) { 00837 block = UT_LIST_GET_LAST(buf_pool->LRU); 00838 } else { 00839 ut_ad(flush_type == BUF_FLUSH_LIST); 00840 00841 block = UT_LIST_GET_LAST(buf_pool->flush_list); 00842 if (!block 00843 || (ut_dulint_cmp(block->oldest_modification, 00844 lsn_limit) >= 0)) { 00845 /* We have flushed enough */ 00846 00847 break; 00848 } 00849 } 00850 00851 found = FALSE; 00852 00853 /* Note that after finding a single flushable page, we try to 00854 flush also all its neighbors, and after that start from the 00855 END of the LRU list or flush list again: the list may change 00856 during the flushing and we cannot safely preserve within this 00857 function a pointer to a block in the list! */ 00858 00859 while ((block != NULL) && !found) { 00860 ut_a(block->state == BUF_BLOCK_FILE_PAGE); 00861 00862 if (buf_flush_ready_for_flush(block, flush_type)) { 00863 00864 found = TRUE; 00865 space = block->space; 00866 offset = block->offset; 00867 00868 mutex_exit(&(buf_pool->mutex)); 00869 00870 old_page_count = page_count; 00871 00872 /* Try to flush also all the neighbors */ 00873 page_count += 00874 buf_flush_try_neighbors(space, offset, 00875 flush_type); 00876 /* fprintf(stderr, 00877 "Flush type %lu, page no %lu, neighb %lu\n", 00878 flush_type, offset, 00879 page_count - old_page_count); */ 00880 00881 mutex_enter(&(buf_pool->mutex)); 00882 00883 } else if (flush_type == BUF_FLUSH_LRU) { 00884 00885 block = UT_LIST_GET_PREV(LRU, block); 00886 } else { 00887 ut_ad(flush_type == BUF_FLUSH_LIST); 00888 00889 block = UT_LIST_GET_PREV(flush_list, block); 00890 } 00891 } 00892 00893 /* If we could not find anything to flush, leave the loop */ 00894 00895 if (!found) { 00896 break; 00897 } 00898 } 00899 00900 (buf_pool->init_flush)[flush_type] = FALSE; 00901 00902 if ((buf_pool->n_flush[flush_type] == 0) 00903 && (buf_pool->init_flush[flush_type] == FALSE)) { 00904 00905 /* The running flush batch has ended */ 00906 00907 os_event_set(buf_pool->no_flush[flush_type]); 00908 } 00909 00910 mutex_exit(&(buf_pool->mutex)); 00911 00912 buf_flush_buffered_writes(); 00913 00914 #ifdef UNIV_DEBUG 00915 if (buf_debug_prints && page_count > 0) { 00916 ut_a(flush_type == BUF_FLUSH_LRU 00917 || flush_type == BUF_FLUSH_LIST); 00918 fprintf(stderr, flush_type == BUF_FLUSH_LRU 00919 ? "Flushed %lu pages in LRU flush\n" 00920 : "Flushed %lu pages in flush list flush\n", 00921 (ulong) page_count); 00922 } 00923 #endif /* UNIV_DEBUG */ 00924 00925 if (page_count != ULINT_UNDEFINED) 00926 srv_buf_pool_flushed+= page_count; 00927 00928 return(page_count); 00929 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void buf_flush_buffered_writes | ( | void | ) | [static] |
Definition at line 224 of file buf0flu.c.
References yaSSL::block, trx_doublewrite_struct::buf_block_arr, BUF_BLOCK_FILE_PAGE, buf_page_print(), FIL_PAGE_END_LSN_OLD_CHKSUM, FIL_PAGE_LSN, trx_doublewrite_struct::first_free, mach_read_from_4(), trx_doublewrite_struct::mutex, mutex_enter, mutex_exit(), NULL, os_aio_simulated_wake_handler_threads(), page_simple_validate(), srv_use_doublewrite_buf, trx_doublewrite, UNIV_PAGE_SIZE, ut_a, ut_error, and ut_print_timestamp().
Referenced by buf_flush_batch(), buf_flush_post_to_doublewrite_buf(), and buf_flush_try_page().
00226 { 00227 buf_block_t* block; 00228 byte* write_buf; 00229 ulint len; 00230 ulint len2; 00231 ulint i; 00232 00233 if (!srv_use_doublewrite_buf || trx_doublewrite == NULL) { 00234 os_aio_simulated_wake_handler_threads(); 00235 00236 return; 00237 } 00238 00239 mutex_enter(&(trx_doublewrite->mutex)); 00240 00241 /* Write first to doublewrite buffer blocks. We use synchronous 00242 aio and thus know that file write has been completed when the 00243 control returns. */ 00244 00245 if (trx_doublewrite->first_free == 0) { 00246 00247 mutex_exit(&(trx_doublewrite->mutex)); 00248 00249 return; 00250 } 00251 00252 for (i = 0; i < trx_doublewrite->first_free; i++) { 00253 00254 block = trx_doublewrite->buf_block_arr[i]; 00255 ut_a(block->state == BUF_BLOCK_FILE_PAGE); 00256 00257 if (mach_read_from_4(block->frame + FIL_PAGE_LSN + 4) 00258 != mach_read_from_4(block->frame + UNIV_PAGE_SIZE 00259 - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { 00260 ut_print_timestamp(stderr); 00261 fprintf(stderr, 00262 " InnoDB: ERROR: The page to be written seems corrupt!\n" 00263 "InnoDB: The lsn fields do not match! Noticed in the buffer pool\n" 00264 "InnoDB: before posting to the doublewrite buffer.\n"); 00265 } 00266 00267 if (block->check_index_page_at_flush 00268 && !page_simple_validate(block->frame)) { 00269 00270 buf_page_print(block->frame); 00271 00272 ut_print_timestamp(stderr); 00273 fprintf(stderr, 00274 " InnoDB: Apparent corruption of an index page n:o %lu in space %lu\n" 00275 "InnoDB: to be written to data file. We intentionally crash server\n" 00276 "InnoDB: to prevent corrupt data from ending up in data\n" 00277 "InnoDB: files.\n", 00278 (ulong) block->offset, (ulong) block->space); 00279 00280 ut_error; 00281 } 00282 } 00283 00284 /* increment the doublewrite flushed pages counter */ 00285 srv_dblwr_pages_written+= trx_doublewrite->first_free; 00286 srv_dblwr_writes++; 00287 00288 if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { 00289 len = TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE; 00290 } else { 00291 len = trx_doublewrite->first_free * UNIV_PAGE_SIZE; 00292 } 00293 00294 fil_io(OS_FILE_WRITE, 00295 TRUE, TRX_SYS_SPACE, 00296 trx_doublewrite->block1, 0, len, 00297 (void*)trx_doublewrite->write_buf, NULL); 00298 00299 write_buf = trx_doublewrite->write_buf; 00300 00301 for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len; len2 += UNIV_PAGE_SIZE) { 00302 if (mach_read_from_4(write_buf + len2 + FIL_PAGE_LSN + 4) 00303 != mach_read_from_4(write_buf + len2 + UNIV_PAGE_SIZE 00304 - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { 00305 ut_print_timestamp(stderr); 00306 fprintf(stderr, 00307 " InnoDB: ERROR: The page to be written seems corrupt!\n" 00308 "InnoDB: The lsn fields do not match! Noticed in the doublewrite block1.\n"); 00309 } 00310 } 00311 00312 if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { 00313 len = (trx_doublewrite->first_free 00314 - TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) * UNIV_PAGE_SIZE; 00315 00316 fil_io(OS_FILE_WRITE, 00317 TRUE, TRX_SYS_SPACE, 00318 trx_doublewrite->block2, 0, len, 00319 (void*)(trx_doublewrite->write_buf 00320 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE), 00321 NULL); 00322 00323 write_buf = trx_doublewrite->write_buf 00324 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE; 00325 for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len; 00326 len2 += UNIV_PAGE_SIZE) { 00327 if (mach_read_from_4(write_buf + len2 00328 + FIL_PAGE_LSN + 4) 00329 != mach_read_from_4(write_buf + len2 00330 + UNIV_PAGE_SIZE 00331 - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { 00332 ut_print_timestamp(stderr); 00333 fprintf(stderr, 00334 " InnoDB: ERROR: The page to be written seems corrupt!\n" 00335 "InnoDB: The lsn fields do not match! Noticed in the doublewrite block2.\n"); 00336 } 00337 } 00338 } 00339 00340 /* Now flush the doublewrite buffer data to disk */ 00341 00342 fil_flush(TRX_SYS_SPACE); 00343 00344 /* We know that the writes have been flushed to disk now 00345 and in recovery we will find them in the doublewrite buffer 00346 blocks. Next do the writes to the intended positions. */ 00347 00348 for (i = 0; i < trx_doublewrite->first_free; i++) { 00349 block = trx_doublewrite->buf_block_arr[i]; 00350 00351 if (mach_read_from_4(block->frame + FIL_PAGE_LSN + 4) 00352 != mach_read_from_4(block->frame + UNIV_PAGE_SIZE 00353 - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { 00354 ut_print_timestamp(stderr); 00355 fprintf(stderr, 00356 " InnoDB: ERROR: The page to be written seems corrupt!\n" 00357 "InnoDB: The lsn fields do not match! Noticed in the buffer pool\n" 00358 "InnoDB: after posting and flushing the doublewrite buffer.\n" 00359 "InnoDB: Page buf fix count %lu, io fix %lu, state %lu\n", 00360 (ulong)block->buf_fix_count, 00361 (ulong)block->io_fix, 00362 (ulong)block->state); 00363 } 00364 ut_a(block->state == BUF_BLOCK_FILE_PAGE); 00365 00366 fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, 00367 FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, 00368 (void*)block->frame, (void*)block); 00369 } 00370 00371 /* Wake possible simulated aio thread to actually post the 00372 writes to the operating system */ 00373 00374 os_aio_simulated_wake_handler_threads(); 00375 00376 /* Wait that all async writes to tablespaces have been posted to 00377 the OS */ 00378 00379 os_aio_wait_until_no_pending_writes(); 00380 00381 /* Now we flush the data to disk (for example, with fsync) */ 00382 00383 fil_flush_file_spaces(FIL_TABLESPACE); 00384 00385 /* We can now reuse the doublewrite memory buffer: */ 00386 00387 trx_doublewrite->first_free = 0; 00388 00389 mutex_exit(&(trx_doublewrite->mutex)); 00390 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void buf_flush_free_margin | ( | void | ) |
Definition at line 998 of file buf0flu.c.
References buf_flush_batch(), BUF_FLUSH_LRU, buf_flush_LRU_recommendation(), buf_flush_wait_batch_end(), and ut_dulint_zero.
Referenced by buf_LRU_get_free_block(), buf_page_create(), buf_read_ibuf_merge_pages(), and buf_read_page().
01000 { 01001 ulint n_to_flush; 01002 ulint n_flushed; 01003 01004 n_to_flush = buf_flush_LRU_recommendation(); 01005 01006 if (n_to_flush > 0) { 01007 n_flushed = buf_flush_batch(BUF_FLUSH_LRU, n_to_flush, 01008 ut_dulint_zero); 01009 if (n_flushed == ULINT_UNDEFINED) { 01010 /* There was an LRU type flush batch already running; 01011 let us wait for it to end */ 01012 01013 buf_flush_wait_batch_end(BUF_FLUSH_LRU); 01014 } 01015 } 01016 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 440 of file buf0flu.c.
References buf_calc_page_new_checksum(), buf_calc_page_old_checksum(), BUF_NO_CHECKSUM_MAGIC, FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, FIL_PAGE_END_LSN_OLD_CHKSUM, FIL_PAGE_LSN, FIL_PAGE_OFFSET, FIL_PAGE_SPACE_OR_CHKSUM, mach_write_to_4(), mach_write_to_8(), and srv_use_checksums.
Referenced by buf_flush_write_block_low(), fil_create_new_single_table_tablespace(), fil_reset_too_high_lsns(), and recv_apply_log_recs_for_backup().
00442 : page */ 00443 dulint newest_lsn, /* in: newest modification lsn to the page */ 00444 ulint space, /* in: space id */ 00445 ulint page_no) /* in: page number */ 00446 { 00447 /* Write the newest modification lsn to the page header and trailer */ 00448 mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn); 00449 00450 mach_write_to_8(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, 00451 newest_lsn); 00452 /* Write the page number and the space id */ 00453 00454 mach_write_to_4(page + FIL_PAGE_OFFSET, page_no); 00455 mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space); 00456 00457 /* Store the new formula checksum */ 00458 00459 mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, 00460 srv_use_checksums ? 00461 buf_calc_page_new_checksum(page) : BUF_NO_CHECKSUM_MAGIC); 00462 00463 /* We overwrite the first 4 bytes of the end lsn field to store 00464 the old formula checksum. Since it depends also on the field 00465 FIL_PAGE_SPACE_OR_CHKSUM, it has to be calculated after storing the 00466 new formula checksum. */ 00467 00468 mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, 00469 srv_use_checksums ? 00470 buf_calc_page_old_checksum(page) : BUF_NO_CHECKSUM_MAGIC); 00471 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void buf_flush_insert_into_flush_list | ( | buf_block_t * | block | ) |
Definition at line 47 of file buf0flu.c.
References yaSSL::block, BUF_BLOCK_FILE_PAGE, buf_flush_validate_low(), buf_pool, buf_pool_struct::mutex, NULL, ut_a, ut_ad, ut_dulint_cmp(), UT_LIST_ADD_FIRST, and UT_LIST_GET_FIRST.
00049 : block which is modified */ 00050 { 00051 #ifdef UNIV_SYNC_DEBUG 00052 ut_ad(mutex_own(&(buf_pool->mutex))); 00053 #endif /* UNIV_SYNC_DEBUG */ 00054 00055 ut_a(block->state == BUF_BLOCK_FILE_PAGE); 00056 00057 ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL) 00058 || (ut_dulint_cmp( 00059 (UT_LIST_GET_FIRST(buf_pool->flush_list)) 00060 ->oldest_modification, 00061 block->oldest_modification) <= 0)); 00062 00063 UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, block); 00064 00065 ut_ad(buf_flush_validate_low()); 00066 }
Here is the call graph for this function:

| void buf_flush_insert_sorted_into_flush_list | ( | buf_block_t * | block | ) |
Definition at line 74 of file buf0flu.c.
References yaSSL::block, buf_flush_validate_low(), buf_pool, buf_pool_struct::mutex, NULL, buf_block_struct::oldest_modification, ut_ad, ut_dulint_cmp(), UT_LIST_ADD_FIRST, UT_LIST_GET_FIRST, UT_LIST_GET_NEXT, and UT_LIST_INSERT_AFTER.
00076 : block which is modified */ 00077 { 00078 buf_block_t* prev_b; 00079 buf_block_t* b; 00080 00081 #ifdef UNIV_SYNC_DEBUG 00082 ut_ad(mutex_own(&(buf_pool->mutex))); 00083 #endif /* UNIV_SYNC_DEBUG */ 00084 00085 prev_b = NULL; 00086 b = UT_LIST_GET_FIRST(buf_pool->flush_list); 00087 00088 while (b && (ut_dulint_cmp(b->oldest_modification, 00089 block->oldest_modification) > 0)) { 00090 prev_b = b; 00091 b = UT_LIST_GET_NEXT(flush_list, b); 00092 } 00093 00094 if (prev_b == NULL) { 00095 UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, block); 00096 } else { 00097 UT_LIST_INSERT_AFTER(flush_list, buf_pool->flush_list, prev_b, 00098 block); 00099 } 00100 00101 ut_ad(buf_flush_validate_low()); 00102 }
Here is the call graph for this function:

| static ulint buf_flush_LRU_recommendation | ( | void | ) | [static] |
Definition at line 950 of file buf0flu.c.
References yaSSL::block, BUF_FLUSH_EXTRA_MARGIN, BUF_FLUSH_FREE_BLOCK_MARGIN, buf_flush_ready_for_replace(), BUF_LRU_FREE_SEARCH_LEN, buf_pool, buf_pool_struct::mutex, mutex_enter, mutex_exit(), NULL, UT_LIST_GET_LAST, UT_LIST_GET_LEN, and UT_LIST_GET_PREV.
Referenced by buf_flush_free_margin().
00952 : number of blocks which should be flushed 00953 from the end of the LRU list */ 00954 { 00955 buf_block_t* block; 00956 ulint n_replaceable; 00957 ulint distance = 0; 00958 00959 mutex_enter(&(buf_pool->mutex)); 00960 00961 n_replaceable = UT_LIST_GET_LEN(buf_pool->free); 00962 00963 block = UT_LIST_GET_LAST(buf_pool->LRU); 00964 00965 while ((block != NULL) 00966 && (n_replaceable < BUF_FLUSH_FREE_BLOCK_MARGIN 00967 + BUF_FLUSH_EXTRA_MARGIN) 00968 && (distance < BUF_LRU_FREE_SEARCH_LEN)) { 00969 00970 if (buf_flush_ready_for_replace(block)) { 00971 n_replaceable++; 00972 } 00973 00974 distance++; 00975 00976 block = UT_LIST_GET_PREV(LRU, block); 00977 } 00978 00979 mutex_exit(&(buf_pool->mutex)); 00980 00981 if (n_replaceable >= BUF_FLUSH_FREE_BLOCK_MARGIN) { 00982 00983 return(0); 00984 } 00985 00986 return(BUF_FLUSH_FREE_BLOCK_MARGIN + BUF_FLUSH_EXTRA_MARGIN 00987 - n_replaceable); 00988 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void buf_flush_post_to_doublewrite_buf | ( | buf_block_t * | block | ) | [static] |
Definition at line 398 of file buf0flu.c.
References yaSSL::block, trx_doublewrite_struct::buf_block_arr, BUF_BLOCK_FILE_PAGE, buf_flush_buffered_writes(), trx_doublewrite_struct::first_free, trx_doublewrite_struct::mutex, mutex_enter, mutex_exit(), trx_doublewrite, TRX_SYS_DOUBLEWRITE_BLOCK_SIZE, ut_a, ut_memcpy(), and trx_doublewrite_struct::write_buf.
Referenced by buf_flush_write_block_low().
00400 : buffer block to write */ 00401 { 00402 try_again: 00403 mutex_enter(&(trx_doublewrite->mutex)); 00404 00405 ut_a(block->state == BUF_BLOCK_FILE_PAGE); 00406 00407 if (trx_doublewrite->first_free 00408 >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { 00409 mutex_exit(&(trx_doublewrite->mutex)); 00410 00411 buf_flush_buffered_writes(); 00412 00413 goto try_again; 00414 } 00415 00416 ut_memcpy(trx_doublewrite->write_buf 00417 + UNIV_PAGE_SIZE * trx_doublewrite->first_free, 00418 block->frame, UNIV_PAGE_SIZE); 00419 00420 trx_doublewrite->buf_block_arr[trx_doublewrite->first_free] = block; 00421 00422 trx_doublewrite->first_free++; 00423 00424 if (trx_doublewrite->first_free 00425 >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { 00426 mutex_exit(&(trx_doublewrite->mutex)); 00427 00428 buf_flush_buffered_writes(); 00429 00430 return; 00431 } 00432 00433 mutex_exit(&(trx_doublewrite->mutex)); 00434 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool buf_flush_ready_for_flush | ( | buf_block_t * | block, | |
| ulint | flush_type | |||
| ) |
Definition at line 142 of file buf0flu.c.
References yaSSL::block, BUF_BLOCK_FILE_PAGE, BUF_FLUSH_LRU, buf_pool, FALSE, buf_pool_struct::mutex, TRUE, ut_a, ut_ad, ut_dulint_cmp(), and ut_dulint_zero.
Referenced by buf_flush_batch(), buf_flush_try_neighbors(), and buf_flush_try_page().
00144 : TRUE if can flush immediately */ 00145 buf_block_t* block, /* in: buffer control block, must be in state 00146 BUF_BLOCK_FILE_PAGE */ 00147 ulint flush_type)/* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */ 00148 { 00149 #ifdef UNIV_SYNC_DEBUG 00150 ut_ad(mutex_own(&(buf_pool->mutex))); 00151 #endif /* UNIV_SYNC_DEBUG */ 00152 ut_a(block->state == BUF_BLOCK_FILE_PAGE); 00153 00154 if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) 00155 && (block->io_fix == 0)) { 00156 if (flush_type != BUF_FLUSH_LRU) { 00157 00158 return(TRUE); 00159 00160 } else if (block->buf_fix_count == 0) { 00161 00162 /* If we are flushing the LRU list, to avoid deadlocks 00163 we require the block not to be bufferfixed, and hence 00164 not latched. */ 00165 00166 return(TRUE); 00167 } 00168 } 00169 00170 return(FALSE); 00171 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool buf_flush_ready_for_replace | ( | buf_block_t * | block | ) |
Definition at line 109 of file buf0flu.c.
References yaSSL::block, BUF_BLOCK_FILE_PAGE, buf_pool, FALSE, buf_pool_struct::mutex, TRUE, ut_ad, ut_dulint_cmp(), ut_dulint_zero, ut_print_buf(), and ut_print_timestamp().
Referenced by buf_all_freed(), buf_flush_LRU_recommendation(), and buf_LRU_search_and_free_block().
00111 : TRUE if can replace immediately */ 00112 buf_block_t* block) /* in: buffer control block, must be in state 00113 BUF_BLOCK_FILE_PAGE and in the LRU list */ 00114 { 00115 #ifdef UNIV_SYNC_DEBUG 00116 ut_ad(mutex_own(&(buf_pool->mutex))); 00117 #endif /* UNIV_SYNC_DEBUG */ 00118 if (block->state != BUF_BLOCK_FILE_PAGE) { 00119 ut_print_timestamp(stderr); 00120 fprintf(stderr, 00121 " InnoDB: Error: buffer block state %lu in the LRU list!\n", 00122 (ulong)block->state); 00123 ut_print_buf(stderr, block, sizeof(buf_block_t)); 00124 00125 return(FALSE); 00126 } 00127 00128 if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) 00129 || (block->buf_fix_count != 0) 00130 || (block->io_fix != 0)) { 00131 00132 return(FALSE); 00133 } 00134 00135 return(TRUE); 00136 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 703 of file buf0flu.c.
References yaSSL::block, BUF_BLOCK_FILE_PAGE, BUF_FLUSH_AREA, BUF_FLUSH_LIST, BUF_FLUSH_LRU, buf_flush_ready_for_flush(), buf_flush_try_page(), BUF_LRU_OLD_MIN_LEN, buf_page_hash_get(), buf_pool, count, fil_space_get_size(), buf_pool_struct::mutex, mutex_enter, mutex_exit(), ut_a, ut_ad, and UT_LIST_GET_LEN.
Referenced by buf_flush_batch().
00705 : number of pages flushed */ 00706 ulint space, /* in: space id */ 00707 ulint offset, /* in: page offset */ 00708 ulint flush_type) /* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */ 00709 { 00710 buf_block_t* block; 00711 ulint low, high; 00712 ulint count = 0; 00713 ulint i; 00714 00715 ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); 00716 00717 low = (offset / BUF_FLUSH_AREA) * BUF_FLUSH_AREA; 00718 high = (offset / BUF_FLUSH_AREA + 1) * BUF_FLUSH_AREA; 00719 00720 if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) { 00721 /* If there is little space, it is better not to flush any 00722 block except from the end of the LRU list */ 00723 00724 low = offset; 00725 high = offset + 1; 00726 } 00727 00728 /* fprintf(stderr, "Flush area: low %lu high %lu\n", low, high); */ 00729 00730 if (high > fil_space_get_size(space)) { 00731 high = fil_space_get_size(space); 00732 } 00733 00734 mutex_enter(&(buf_pool->mutex)); 00735 00736 for (i = low; i < high; i++) { 00737 00738 block = buf_page_hash_get(space, i); 00739 ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); 00740 00741 if (block && flush_type == BUF_FLUSH_LRU && i != offset 00742 && !block->old) { 00743 00744 /* We avoid flushing 'non-old' blocks in an LRU flush, 00745 because the flushed blocks are soon freed */ 00746 00747 continue; 00748 } 00749 00750 if (block && buf_flush_ready_for_flush(block, flush_type) 00751 && (i == offset || block->buf_fix_count == 0)) { 00752 /* We only try to flush those neighbors != offset 00753 where the buf fix count is zero, as we then know that 00754 we probably can latch the page without a semaphore 00755 wait. Semaphore waits are expensive because we must 00756 flush the doublewrite buffer before we start 00757 waiting. */ 00758 00759 mutex_exit(&(buf_pool->mutex)); 00760 00761 /* Note: as we release the buf_pool mutex above, in 00762 buf_flush_try_page we cannot be sure the page is still 00763 in a flushable state: therefore we check it again 00764 inside that function. */ 00765 00766 count += buf_flush_try_page(space, i, flush_type); 00767 00768 mutex_enter(&(buf_pool->mutex)); 00769 } 00770 } 00771 00772 mutex_exit(&(buf_pool->mutex)); 00773 00774 return(count); 00775 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 523 of file buf0flu.c.
References yaSSL::block, buf_awe_map_page_to_frame(), BUF_BLOCK_FILE_PAGE, buf_flush_buffered_writes(), BUF_FLUSH_LIST, BUF_FLUSH_LRU, buf_flush_ready_for_flush(), BUF_FLUSH_SINGLE_PAGE, buf_flush_write_block_low(), BUF_IO_WRITE, buf_page_hash_get(), buf_pool, FALSE, buf_pool_struct::mutex, mutex_enter, mutex_exit(), buf_pool_struct::n_flush, buf_pool_struct::no_flush, NULL, os_event_reset(), rw_lock_s_lock_gen, srv_use_awe, TRUE, ut_a, and ut_ad.
Referenced by buf_flush_try_neighbors().
00525 : 1 if a page was flushed, 0 otherwise */ 00526 ulint space, /* in: space id */ 00527 ulint offset, /* in: page offset */ 00528 ulint flush_type) /* in: BUF_FLUSH_LRU, BUF_FLUSH_LIST, or 00529 BUF_FLUSH_SINGLE_PAGE */ 00530 { 00531 buf_block_t* block; 00532 ibool locked; 00533 00534 ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST 00535 || flush_type == BUF_FLUSH_SINGLE_PAGE); 00536 00537 mutex_enter(&(buf_pool->mutex)); 00538 00539 block = buf_page_hash_get(space, offset); 00540 00541 ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); 00542 00543 if (flush_type == BUF_FLUSH_LIST 00544 && block && buf_flush_ready_for_flush(block, flush_type)) { 00545 00546 block->io_fix = BUF_IO_WRITE; 00547 00548 /* If AWE is enabled and the page is not mapped to a frame, 00549 then map it */ 00550 00551 if (block->frame == NULL) { 00552 ut_a(srv_use_awe); 00553 00554 /* We set second parameter TRUE because the block is 00555 in the LRU list and we must put it to 00556 awe_LRU_free_mapped list once mapped to a frame */ 00557 00558 buf_awe_map_page_to_frame(block, TRUE); 00559 } 00560 00561 block->flush_type = flush_type; 00562 00563 if (buf_pool->n_flush[flush_type] == 0) { 00564 00565 os_event_reset(buf_pool->no_flush[flush_type]); 00566 } 00567 00568 (buf_pool->n_flush[flush_type])++; 00569 00570 locked = FALSE; 00571 00572 /* If the simulated aio thread is not running, we must 00573 not wait for any latch, as we may end up in a deadlock: 00574 if buf_fix_count == 0, then we know we need not wait */ 00575 00576 if (block->buf_fix_count == 0) { 00577 rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE); 00578 00579 locked = TRUE; 00580 } 00581 00582 mutex_exit(&(buf_pool->mutex)); 00583 00584 if (!locked) { 00585 buf_flush_buffered_writes(); 00586 00587 rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE); 00588 } 00589 00590 #ifdef UNIV_DEBUG 00591 if (buf_debug_prints) { 00592 fprintf(stderr, 00593 "Flushing page space %lu, page no %lu \n", 00594 (ulong) block->space, (ulong) block->offset); 00595 } 00596 #endif /* UNIV_DEBUG */ 00597 00598 buf_flush_write_block_low(block); 00599 00600 return(1); 00601 00602 } else if (flush_type == BUF_FLUSH_LRU && block 00603 && buf_flush_ready_for_flush(block, flush_type)) { 00604 00605 /* VERY IMPORTANT: 00606 Because any thread may call the LRU flush, even when owning 00607 locks on pages, to avoid deadlocks, we must make sure that the 00608 s-lock is acquired on the page without waiting: this is 00609 accomplished because in the if-condition above we require 00610 the page not to be bufferfixed (in function 00611 ..._ready_for_flush). */ 00612 00613 block->io_fix = BUF_IO_WRITE; 00614 00615 /* If AWE is enabled and the page is not mapped to a frame, 00616 then map it */ 00617 00618 if (block->frame == NULL) { 00619 ut_a(srv_use_awe); 00620 00621 /* We set second parameter TRUE because the block is 00622 in the LRU list and we must put it to 00623 awe_LRU_free_mapped list once mapped to a frame */ 00624 00625 buf_awe_map_page_to_frame(block, TRUE); 00626 } 00627 00628 block->flush_type = flush_type; 00629 00630 if (buf_pool->n_flush[flush_type] == 0) { 00631 00632 os_event_reset(buf_pool->no_flush[flush_type]); 00633 } 00634 00635 (buf_pool->n_flush[flush_type])++; 00636 00637 rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE); 00638 00639 /* Note that the s-latch is acquired before releasing the 00640 buf_pool mutex: this ensures that the latch is acquired 00641 immediately. */ 00642 00643 mutex_exit(&(buf_pool->mutex)); 00644 00645 buf_flush_write_block_low(block); 00646 00647 return(1); 00648 00649 } else if (flush_type == BUF_FLUSH_SINGLE_PAGE && block 00650 && buf_flush_ready_for_flush(block, flush_type)) { 00651 00652 block->io_fix = BUF_IO_WRITE; 00653 00654 /* If AWE is enabled and the page is not mapped to a frame, 00655 then map it */ 00656 00657 if (block->frame == NULL) { 00658 ut_a(srv_use_awe); 00659 00660 /* We set second parameter TRUE because the block is 00661 in the LRU list and we must put it to 00662 awe_LRU_free_mapped list once mapped to a frame */ 00663 00664 buf_awe_map_page_to_frame(block, TRUE); 00665 } 00666 00667 block->flush_type = flush_type; 00668 00669 if (buf_pool->n_flush[block->flush_type] == 0) { 00670 00671 os_event_reset(buf_pool->no_flush[block->flush_type]); 00672 } 00673 00674 (buf_pool->n_flush[flush_type])++; 00675 00676 mutex_exit(&(buf_pool->mutex)); 00677 00678 rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE); 00679 00680 #ifdef UNIV_DEBUG 00681 if (buf_debug_prints) { 00682 fprintf(stderr, 00683 "Flushing single page space %lu, page no %lu \n", 00684 (ulong) block->space, 00685 (ulong) block->offset); 00686 } 00687 #endif /* UNIV_DEBUG */ 00688 00689 buf_flush_write_block_low(block); 00690 00691 return(1); 00692 } else { 00693 mutex_exit(&(buf_pool->mutex)); 00694 00695 return(0); 00696 } 00697 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool buf_flush_validate | ( | void | ) |
Definition at line 1053 of file buf0flu.c.
References buf_flush_validate_low(), buf_pool, buf_pool_struct::mutex, mutex_enter, and mutex_exit().
01055 : TRUE if ok */ 01056 { 01057 ibool ret; 01058 01059 mutex_enter(&(buf_pool->mutex)); 01060 01061 ret = buf_flush_validate_low(); 01062 01063 mutex_exit(&(buf_pool->mutex)); 01064 01065 return(ret); 01066 }
Here is the call graph for this function:

| static ibool buf_flush_validate_low | ( | void | ) | [static] |
Definition at line 1022 of file buf0flu.c.
References yaSSL::block, BUF_BLOCK_FILE_PAGE, buf_pool, NULL, TRUE, ut_a, ut_dulint_cmp(), ut_dulint_zero, UT_LIST_GET_FIRST, UT_LIST_GET_NEXT, and UT_LIST_VALIDATE.
Referenced by buf_flush_insert_into_flush_list(), buf_flush_insert_sorted_into_flush_list(), and buf_flush_validate().
01024 : TRUE if ok */ 01025 { 01026 buf_block_t* block; 01027 dulint om; 01028 01029 UT_LIST_VALIDATE(flush_list, buf_block_t, buf_pool->flush_list); 01030 01031 block = UT_LIST_GET_FIRST(buf_pool->flush_list); 01032 01033 while (block != NULL) { 01034 om = block->oldest_modification; 01035 ut_a(block->state == BUF_BLOCK_FILE_PAGE); 01036 ut_a(ut_dulint_cmp(om, ut_dulint_zero) > 0); 01037 01038 block = UT_LIST_GET_NEXT(flush_list, block); 01039 01040 if (block) { 01041 ut_a(ut_dulint_cmp(om, block->oldest_modification) 01042 >= 0); 01043 } 01044 } 01045 01046 return(TRUE); 01047 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void buf_flush_wait_batch_end | ( | ulint | type | ) |
Definition at line 935 of file buf0flu.c.
References BUF_FLUSH_LIST, BUF_FLUSH_LRU, buf_pool, buf_pool_struct::no_flush, os_event_wait(), and ut_ad.
Referenced by buf_flush_free_margin(), log_preflush_pool_modified_pages(), recv_apply_hashed_log_recs(), and srv_master_thread().
00937 : BUF_FLUSH_LRU or BUF_FLUSH_LIST */ 00938 { 00939 ut_ad((type == BUF_FLUSH_LRU) || (type == BUF_FLUSH_LIST)); 00940 00941 os_event_wait(buf_pool->no_flush[type]); 00942 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void buf_flush_write_block_low | ( | buf_block_t * | block | ) | [static] |
Definition at line 479 of file buf0flu.c.
References yaSSL::block, BUF_BLOCK_FILE_PAGE, buf_flush_init_for_writing(), buf_flush_post_to_doublewrite_buf(), FALSE, fil_io(), LOG_WAIT_ALL_GROUPS, log_write_up_to(), OS_AIO_SIMULATED_WAKE_LATER, OS_FILE_WRITE, srv_use_doublewrite_buf, TRUE, trx_doublewrite, ut_a, ut_ad, and ut_dulint_is_zero().
Referenced by buf_flush_try_page().
00481 : buffer block to write */ 00482 { 00483 #ifdef UNIV_LOG_DEBUG 00484 static ibool univ_log_debug_warned; 00485 #endif /* UNIV_LOG_DEBUG */ 00486 ut_a(block->state == BUF_BLOCK_FILE_PAGE); 00487 00488 #ifdef UNIV_IBUF_DEBUG 00489 ut_a(ibuf_count_get(block->space, block->offset) == 0); 00490 #endif 00491 ut_ad(!ut_dulint_is_zero(block->newest_modification)); 00492 00493 #ifdef UNIV_LOG_DEBUG 00494 if (!univ_log_debug_warned) { 00495 univ_log_debug_warned = TRUE; 00496 fputs( 00497 "Warning: cannot force log to disk if UNIV_LOG_DEBUG is defined!\n" 00498 "Crash recovery will not work!\n", 00499 stderr); 00500 } 00501 #else 00502 /* Force the log to the disk before writing the modified block */ 00503 log_write_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS, TRUE); 00504 #endif 00505 buf_flush_init_for_writing(block->frame, block->newest_modification, 00506 block->space, block->offset); 00507 if (!srv_use_doublewrite_buf || !trx_doublewrite) { 00508 fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, 00509 FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, 00510 (void*)block->frame, (void*)block); 00511 } else { 00512 buf_flush_post_to_doublewrite_buf(block); 00513 } 00514 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void buf_flush_write_complete | ( | buf_block_t * | block | ) |
Definition at line 177 of file buf0flu.c.
References yaSSL::block, BUF_BLOCK_FILE_PAGE, BUF_FLUSH_LRU, buf_LRU_make_block_old(), buf_pool, FALSE, buf_pool_struct::init_flush, buf_pool_struct::LRU_flush_ended, buf_pool_struct::mutex, buf_pool_struct::n_flush, buf_pool_struct::no_flush, os_event_set(), ut_a, ut_ad, ut_d, ut_dulint_zero, UT_LIST_REMOVE, and UT_LIST_VALIDATE.
Referenced by buf_page_io_complete().
00179 : pointer to the block in question */ 00180 { 00181 ut_ad(block); 00182 #ifdef UNIV_SYNC_DEBUG 00183 ut_ad(mutex_own(&(buf_pool->mutex))); 00184 #endif /* UNIV_SYNC_DEBUG */ 00185 ut_a(block->state == BUF_BLOCK_FILE_PAGE); 00186 00187 block->oldest_modification = ut_dulint_zero; 00188 00189 UT_LIST_REMOVE(flush_list, buf_pool->flush_list, block); 00190 00191 ut_d(UT_LIST_VALIDATE(flush_list, buf_block_t, buf_pool->flush_list)); 00192 00193 (buf_pool->n_flush[block->flush_type])--; 00194 00195 if (block->flush_type == BUF_FLUSH_LRU) { 00196 /* Put the block to the end of the LRU list to wait to be 00197 moved to the free list */ 00198 00199 buf_LRU_make_block_old(block); 00200 00201 buf_pool->LRU_flush_ended++; 00202 } 00203 00204 /* fprintf(stderr, "n pending flush %lu\n", 00205 buf_pool->n_flush[block->flush_type]); */ 00206 00207 if ((buf_pool->n_flush[block->flush_type] == 0) 00208 && (buf_pool->init_flush[block->flush_type] == FALSE)) { 00209 00210 /* The running flush batch has ended */ 00211 00212 os_event_set(buf_pool->no_flush[block->flush_type]); 00213 } 00214 }
Here is the call graph for this function:

Here is the caller graph for this function:

1.4.7

