1/***************************************************************************** 2 3Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. 4 5This program is free software; you can redistribute it and/or modify it under 6the terms of the GNU General Public License as published by the Free Software 7Foundation; version 2 of the License. 8 9This program is distributed in the hope that it will be useful, but WITHOUT 10ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13You should have received a copy of the GNU General Public License along with 14this program; if not, write to the Free Software Foundation, Inc., 1551 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 16 17*****************************************************************************/ 18 19/**************************************************//** 20@file include/buf0flu.ic 21The database buffer pool flush algorithm 22 23Created 11/5/1995 Heikki Tuuri 24*******************************************************/ 25 26#include "buf0buf.h" 27#include "mtr0mtr.h" 28#include "srv0srv.h" 29#include "fsp0types.h" 30 31/********************************************************************//** 32Inserts a modified block into the flush list. */ 33void 34buf_flush_insert_into_flush_list( 35/*=============================*/ 36 buf_pool_t* buf_pool, /*!< buffer pool instance */ 37 buf_block_t* block, /*!< in/out: block which is modified */ 38 lsn_t lsn); /*!< in: oldest modification */ 39 40/********************************************************************//** 41Inserts a modified block into the flush list in the right sorted position. 42This function is used by recovery, because there the modifications do not 43necessarily come in the order of lsn's. */ 44void 45buf_flush_insert_sorted_into_flush_list( 46/*====================================*/ 47 buf_pool_t* buf_pool, /*!< buffer pool instance */ 48 buf_block_t* block, /*!< in/out: block which is modified */ 49 lsn_t lsn); /*!< in: oldest modification */ 50 51/********************************************************************//** 52This function should be called at a mini-transaction commit, if a page was 53modified in it. Puts the block to the list of modified blocks, if it is not 54already in it. */ 55UNIV_INLINE 56void 57buf_flush_note_modification( 58/*========================*/ 59 buf_block_t* block, /*!< in: block which is modified */ 60 lsn_t start_lsn, /*!< in: start lsn of the mtr that 61 modified this block */ 62 lsn_t end_lsn, /*!< in: end lsn of the mtr that 63 modified this block */ 64 FlushObserver* observer) /*!< in: flush observer */ 65{ 66#ifdef UNIV_DEBUG 67 { 68 /* Allow write to proceed to shared temporary tablespace 69 in read-only mode. */ 70 ut_ad(!srv_read_only_mode 71 || fsp_is_system_temporary(block->page.id.space())); 72 ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); 73 ut_ad(block->page.buf_fix_count > 0); 74 75 buf_pool_t* buf_pool = buf_pool_from_block(block); 76 77 ut_ad(!buf_pool_mutex_own(buf_pool)); 78 ut_ad(!buf_flush_list_mutex_own(buf_pool)); 79 } 80#endif /* UNIV_DEBUG */ 81 82 mutex_enter(&block->mutex); 83 84 ut_ad(block->page.newest_modification <= end_lsn); 85 block->page.newest_modification = end_lsn; 86 87 /* Don't allow to set flush observer from non-null to null, 88 or from one observer to another. */ 89 ut_ad(block->page.flush_observer == NULL 90 || block->page.flush_observer == observer); 91 block->page.flush_observer = observer; 92 93 if (block->page.oldest_modification == 0) { 94 buf_pool_t* buf_pool = buf_pool_from_block(block); 95 96 buf_flush_insert_into_flush_list(buf_pool, block, start_lsn); 97 } else { 98 ut_ad(block->page.oldest_modification <= start_lsn); 99 } 100 101 buf_page_mutex_exit(block); 102 103 srv_stats.buf_pool_write_requests.inc(); 104} 105 106/********************************************************************//** 107This function should be called when recovery has modified a buffer page. */ 108UNIV_INLINE 109void 110buf_flush_recv_note_modification( 111/*=============================*/ 112 buf_block_t* block, /*!< in: block which is modified */ 113 lsn_t start_lsn, /*!< in: start lsn of the first mtr in a 114 set of mtr's */ 115 lsn_t end_lsn) /*!< in: end lsn of the last mtr in the 116 set of mtr's */ 117{ 118#ifdef UNIV_DEBUG 119 { 120 ut_ad(!srv_read_only_mode); 121 ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); 122 ut_ad(block->page.buf_fix_count > 0); 123 124 buf_pool_t* buf_pool = buf_pool_from_block(block); 125 126 ut_ad(!buf_pool_mutex_own(buf_pool)); 127 ut_ad(!buf_flush_list_mutex_own(buf_pool)); 128 129 ut_ad(start_lsn != 0); 130 ut_ad(block->page.newest_modification <= end_lsn); 131 } 132#endif /* UNIV_DEBUG */ 133 134 buf_page_mutex_enter(block); 135 136 block->page.newest_modification = end_lsn; 137 138 if (!block->page.oldest_modification) { 139 buf_pool_t* buf_pool = buf_pool_from_block(block); 140 141 buf_flush_insert_sorted_into_flush_list( 142 buf_pool, block, start_lsn); 143 } else { 144 ut_ad(block->page.oldest_modification <= start_lsn); 145 } 146 147 buf_page_mutex_exit(block); 148 149} 150