| 1 | /***************************************************************************** |
| 2 | |
| 3 | Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. |
| 4 | |
| 5 | This program is free software; you can redistribute it and/or modify it under |
| 6 | the terms of the GNU General Public License as published by the Free Software |
| 7 | Foundation; version 2 of the License. |
| 8 | |
| 9 | This program is distributed in the hope that it will be useful, but WITHOUT |
| 10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 11 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| 12 | |
| 13 | You should have received a copy of the GNU General Public License along with |
| 14 | this program; if not, write to the Free Software Foundation, Inc., |
| 15 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
| 16 | |
| 17 | *****************************************************************************/ |
| 18 | |
| 19 | /**************************************************//** |
| 20 | @file include/buf0flu.ic |
| 21 | The database buffer pool flush algorithm |
| 22 | |
| 23 | Created 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 | /********************************************************************//** |
| 32 | Inserts a modified block into the flush list. */ |
| 33 | void |
| 34 | buf_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 | /********************************************************************//** |
| 41 | Inserts a modified block into the flush list in the right sorted position. |
| 42 | This function is used by recovery, because there the modifications do not |
| 43 | necessarily come in the order of lsn's. */ |
| 44 | void |
| 45 | buf_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 | /********************************************************************//** |
| 52 | This function should be called at a mini-transaction commit, if a page was |
| 53 | modified in it. Puts the block to the list of modified blocks, if it is not |
| 54 | already in it. */ |
| 55 | UNIV_INLINE |
| 56 | void |
| 57 | buf_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 | /********************************************************************//** |
| 107 | This function should be called when recovery has modified a buffer page. */ |
| 108 | UNIV_INLINE |
| 109 | void |
| 110 | buf_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 | |