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, Suite 500, 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