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 | |