1 /*****************************************************************************
2 
3 Copyright (c) 1997, 2021, Oracle and/or its affiliates.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file include/log0recv.h
29 Recovery
30 
31 Created 9/20/1997 Heikki Tuuri
32 *******************************************************/
33 
34 #ifndef log0recv_h
35 #define log0recv_h
36 
37 #include "univ.i"
38 #include "ut0byte.h"
39 #include "buf0types.h"
40 #include "hash0hash.h"
41 #include "log0log.h"
42 #include "mtr0types.h"
43 #include "ut0new.h"
44 
45 #include <list>
46 #include <vector>
47 
48 #ifdef UNIV_HOTBACKUP
49 extern bool	recv_replay_file_ops;
50 
51 /*******************************************************************//**
52 Reads the checkpoint info needed in hot backup.
53 @return TRUE if success */
54 ibool
55 recv_read_checkpoint_info_for_backup(
56 /*=================================*/
57 	const byte*	hdr,	/*!< in: buffer containing the log group
58 				header */
59 	lsn_t*		lsn,	/*!< out: checkpoint lsn */
60 	lsn_t*		offset,	/*!< out: checkpoint offset in the log group */
61 	lsn_t*		cp_no,	/*!< out: checkpoint number */
62 	lsn_t*		first_header_lsn)
63 				/*!< out: lsn of of the start of the
64 				first log file */
65 	MY_ATTRIBUTE((nonnull));
66 /*******************************************************************//**
67 Scans the log segment and n_bytes_scanned is set to the length of valid
68 log scanned. */
69 void
70 recv_scan_log_seg_for_backup(
71 /*=========================*/
72 	byte*		buf,		/*!< in: buffer containing log data */
73 	ulint		buf_len,	/*!< in: data length in that buffer */
74 	lsn_t*		scanned_lsn,	/*!< in/out: lsn of buffer start,
75 					we return scanned lsn */
76 	ulint*		scanned_checkpoint_no,
77 					/*!< in/out: 4 lowest bytes of the
78 					highest scanned checkpoint number so
79 					far */
80 	ulint*		n_bytes_scanned);/*!< out: how much we were able to
81 					scan, smaller than buf_len if log
82 					data ended here */
83 #endif /* UNIV_HOTBACKUP */
84 /*******************************************************************//**
85 Returns TRUE if recovery is currently running.
86 @return recv_recovery_on */
87 UNIV_INLINE
88 bool
89 recv_recovery_is_on(void);
90 /*=====================*/
91 /************************************************************************//**
92 Applies the hashed log records to the page, if the page lsn is less than the
93 lsn of a log record. This can be called when a buffer page has just been
94 read in, or also for a page already in the buffer pool. */
95 void
96 recv_recover_page_func(
97 /*===================*/
98 #ifndef UNIV_HOTBACKUP
99 	ibool		just_read_in,
100 				/*!< in: TRUE if the i/o handler calls
101 				this for a freshly read page */
102 #endif /* !UNIV_HOTBACKUP */
103 	buf_block_t*	block);	/*!< in/out: buffer block */
104 #ifndef UNIV_HOTBACKUP
105 /** Wrapper for recv_recover_page_func().
106 Applies the hashed log records to the page, if the page lsn is less than the
107 lsn of a log record. This can be called when a buffer page has just been
108 read in, or also for a page already in the buffer pool.
109 @param jri in: TRUE if just read in (the i/o handler calls this for
110 a freshly read page)
111 @param block in/out: the buffer block
112 */
113 # define recv_recover_page(jri, block)	recv_recover_page_func(jri, block)
114 #else /* !UNIV_HOTBACKUP */
115 /** Wrapper for recv_recover_page_func().
116 Applies the hashed log records to the page, if the page lsn is less than the
117 lsn of a log record. This can be called when a buffer page has just been
118 read in, or also for a page already in the buffer pool.
119 @param jri in: TRUE if just read in (the i/o handler calls this for
120 a freshly read page)
121 @param block in/out: the buffer block
122 */
123 # define recv_recover_page(jri, block)	recv_recover_page_func(block)
124 #endif /* !UNIV_HOTBACKUP */
125 /** Start recovering from a redo log checkpoint.
126 @see recv_recovery_from_checkpoint_finish
127 @param[in]	flush_lsn	FIL_PAGE_FILE_FLUSH_LSN
128 of first system tablespace page
129 @return error code or DB_SUCCESS */
130 dberr_t
131 recv_recovery_from_checkpoint_start(
132 	lsn_t	flush_lsn);
133 /** Complete recovery from a checkpoint. */
134 void
135 recv_recovery_from_checkpoint_finish(void);
136 /********************************************************//**
137 Initiates the rollback of active transactions. */
138 void
139 recv_recovery_rollback_active(void);
140 /*===============================*/
141 /******************************************************//**
142 Resets the logs. The contents of log files will be lost! */
143 void
144 recv_reset_logs(
145 /*============*/
146 	lsn_t		lsn);		/*!< in: reset to this lsn
147 					rounded up to be divisible by
148 					OS_FILE_LOG_BLOCK_SIZE, after
149 					which we add
150 					LOG_BLOCK_HDR_SIZE */
151 #ifdef UNIV_HOTBACKUP
152 /******************************************************//**
153 Creates new log files after a backup has been restored. */
154 void
155 recv_reset_log_files_for_backup(
156 /*============================*/
157 	const char*	log_dir,	/*!< in: log file directory path */
158 	ulint		n_log_files,	/*!< in: number of log files */
159 	lsn_t		log_file_size,	/*!< in: log file size */
160 	lsn_t		lsn);		/*!< in: new start lsn, must be
161 					divisible by OS_FILE_LOG_BLOCK_SIZE */
162 #endif /* UNIV_HOTBACKUP */
163 /********************************************************//**
164 Creates the recovery system. */
165 void
166 recv_sys_create(void);
167 /*=================*/
168 /**********************************************************//**
169 Release recovery system mutexes. */
170 void
171 recv_sys_close(void);
172 /*================*/
173 /********************************************************//**
174 Frees the recovery system memory. */
175 void
176 recv_sys_mem_free(void);
177 /*===================*/
178 /********************************************************//**
179 Inits the recovery system for a recovery operation. */
180 void
181 recv_sys_init(
182 /*==========*/
183 	ulint	available_memory);	/*!< in: available memory in bytes */
184 #ifndef UNIV_HOTBACKUP
185 /********************************************************//**
186 Frees the recovery system. */
187 void
188 recv_sys_debug_free(void);
189 /*=====================*/
190 /********************************************************//**
191 Reset the state of the recovery system variables. */
192 void
193 recv_sys_var_init(void);
194 /*===================*/
195 #endif /* !UNIV_HOTBACKUP */
196 /*******************************************************************//**
197 Empties the hash table of stored log records, applying them to appropriate
198 pages. */
199 void
200 recv_apply_hashed_log_recs(
201 /*=======================*/
202 	ibool	allow_ibuf);	/*!< in: if TRUE, also ibuf operations are
203 				allowed during the application; if FALSE,
204 				no ibuf operations are allowed, and after
205 				the application all file pages are flushed to
206 				disk and invalidated in buffer pool: this
207 				alternative means that no new log records
208 				can be generated during the application */
209 #ifdef UNIV_HOTBACKUP
210 /*******************************************************************//**
211 Applies log records in the hash table to a backup. */
212 void
213 recv_apply_log_recs_for_backup(void);
214 /*================================*/
215 #endif /* UNIV_HOTBACKUP */
216 
217 /** Block of log record data */
218 struct recv_data_t{
219 	recv_data_t*	next;	/*!< pointer to the next block or NULL */
220 				/*!< the log record data is stored physically
221 				immediately after this struct, max amount
222 				RECV_DATA_BLOCK_SIZE bytes of it */
223 };
224 
225 /** Stored log record struct */
226 struct recv_t{
227 	mlog_id_t	type;	/*!< log record type */
228 	ulint		len;	/*!< log record body length in bytes */
229 	recv_data_t*	data;	/*!< chain of blocks containing the log record
230 				body */
231 	lsn_t		start_lsn;/*!< start lsn of the log segment written by
232 				the mtr which generated this log record: NOTE
233 				that this is not necessarily the start lsn of
234 				this log record */
235 	lsn_t		end_lsn;/*!< end lsn of the log segment written by
236 				the mtr which generated this log record: NOTE
237 				that this is not necessarily the end lsn of
238 				this log record */
239 	UT_LIST_NODE_T(recv_t)
240 			rec_list;/*!< list of log records for this page */
241 };
242 
243 /** States of recv_addr_t */
244 enum recv_addr_state {
245 	/** not yet processed */
246 	RECV_NOT_PROCESSED,
247 	/** page is being read */
248 	RECV_BEING_READ,
249 	/** log records are being applied on the page */
250 	RECV_BEING_PROCESSED,
251 	/** log records have been applied on the page */
252 	RECV_PROCESSED,
253 	/** log records have been discarded because the tablespace
254 	does not exist */
255 	RECV_DISCARDED
256 };
257 
258 /** Hashed page file address struct */
259 struct recv_addr_t{
260 	enum recv_addr_state state;
261 				/*!< recovery state of the page */
262 	unsigned	space:32;/*!< space id */
263 	unsigned	page_no:32;/*!< page number */
264 	UT_LIST_BASE_NODE_T(recv_t)
265 			rec_list;/*!< list of log records for this page */
266 	hash_node_t	addr_hash;/*!< hash node in the hash bucket chain */
267 };
268 
269 struct recv_dblwr_t {
270 	/** Add a page frame to the doublewrite recovery buffer. */
addrecv_dblwr_t271 	void add(const byte* page) {
272 		pages.push_back(page);
273 	}
274 
275 	/** Find a doublewrite copy of a page.
276 	@param[in]	space_id	tablespace identifier
277 	@param[in]	page_no		page number
278 	@return	page frame
279 	@retval NULL if no page was found */
280 	const byte* find_page(ulint space_id, ulint page_no);
281 
282 	typedef std::list<const byte*, ut_allocator<const byte*> >	list;
283 
284 	/** Recovered doublewrite buffer page frames */
285 	list	pages;
286 };
287 
288 /* Recovery encryption information */
289 typedef	struct recv_encryption {
290 	ulint		space_id;	/*!< the page number */
291 	byte*		key;		/*!< encryption key */
292 	byte*		iv;		/*!< encryption iv */
293 } recv_encryption_t;
294 
295 typedef std::vector<recv_encryption_t, ut_allocator<recv_encryption_t> >
296 		encryption_list_t;
297 
298 /** Recovery system data structure */
299 struct recv_sys_t{
300 #ifndef UNIV_HOTBACKUP
301 	ib_mutex_t		mutex;	/*!< mutex protecting the fields apply_log_recs,
302 				n_addrs, and the state field in each recv_addr
303 				struct */
304 	ib_mutex_t		writer_mutex;/*!< mutex coordinating
305 				flushing between recv_writer_thread and
306 				the recovery thread. */
307 	os_event_t		flush_start;/*!< event to acticate
308 				page cleaner threads */
309 	os_event_t		flush_end;/*!< event to signal that the page
310 				cleaner has finished the request */
311 	buf_flush_t		flush_type;/*!< type of the flush request.
312 				BUF_FLUSH_LRU: flush end of LRU, keeping free blocks.
313 				BUF_FLUSH_LIST: flush all of blocks. */
314 #endif /* !UNIV_HOTBACKUP */
315 	ibool		apply_log_recs;
316 				/*!< this is TRUE when log rec application to
317 				pages is allowed; this flag tells the
318 				i/o-handler if it should do log record
319 				application */
320 	ibool		apply_batch_on;
321 				/*!< this is TRUE when a log rec application
322 				batch is running */
323 	byte*		last_block;
324 				/*!< possible incomplete last recovered log
325 				block */
326 	byte*		last_block_buf_start;
327 				/*!< the nonaligned start address of the
328 				preceding buffer */
329 	byte*		buf;	/*!< buffer for parsing log records */
330 	ulint		len;	/*!< amount of data in buf */
331 	lsn_t		parse_start_lsn;
332 				/*!< this is the lsn from which we were able to
333 				start parsing log records and adding them to
334 				the hash table; zero if a suitable
335 				start point not found yet */
336 	lsn_t		scanned_lsn;
337 				/*!< the log data has been scanned up to this
338 				lsn */
339 	ulint		scanned_checkpoint_no;
340 				/*!< the log data has been scanned up to this
341 				checkpoint number (lowest 4 bytes) */
342 	ulint		recovered_offset;
343 				/*!< start offset of non-parsed log records in
344 				buf */
345 	lsn_t		recovered_lsn;
346 				/*!< the log records have been parsed up to
347 				this lsn */
348 	bool		found_corrupt_log;
349 				/*!< set when finding a corrupt log
350 				block or record, or there is a log
351 				parsing buffer overflow */
352 	bool		found_corrupt_fs;
353 				/*!< set when an inconsistency with
354 				the file system contents is detected
355 				during log scan or apply */
356 	lsn_t		mlog_checkpoint_lsn;
357 				/*!< the LSN of a MLOG_CHECKPOINT
358 				record, or 0 if none was parsed */
359 	mem_heap_t*	heap;	/*!< memory heap of log records and file
360 				addresses*/
361 	hash_table_t*	addr_hash;/*!< hash table of file addresses of pages */
362 	ulint		n_addrs;/*!< number of not processed hashed file
363 				addresses in the hash table */
364 
365 	recv_dblwr_t	dblwr;
366 
367 	encryption_list_t*	/*!< Encryption information list */
368 			encryption_list;
369 };
370 
371 /** The recovery system */
372 extern recv_sys_t*	recv_sys;
373 
374 /** TRUE when applying redo log records during crash recovery; FALSE
375 otherwise.  Note that this is FALSE while a background thread is
376 rolling back incomplete transactions. */
377 extern volatile bool	recv_recovery_on;
378 /** If the following is TRUE, the buffer pool file pages must be invalidated
379 after recovery and no ibuf operations are allowed; this becomes TRUE if
380 the log record hash table becomes too full, and log records must be merged
381 to file pages already before the recovery is finished: in this case no
382 ibuf operations are allowed, as they could modify the pages read in the
383 buffer pool before the pages have been recovered to the up-to-date state.
384 
385 TRUE means that recovery is running and no operations on the log files
386 are allowed yet: the variable name is misleading. */
387 extern bool		recv_no_ibuf_operations;
388 /** TRUE when recv_init_crash_recovery() has been called. */
389 extern bool		recv_needed_recovery;
390 #ifdef UNIV_DEBUG
391 /** TRUE if writing to the redo log (mtr_commit) is forbidden.
392 Protected by log_sys->mutex. */
393 extern bool		recv_no_log_write;
394 #endif /* UNIV_DEBUG */
395 
396 /** TRUE if buf_page_is_corrupted() should check if the log sequence
397 number (FIL_PAGE_LSN) is in the future.  Initially FALSE, and set by
398 recv_recovery_from_checkpoint_start(). */
399 extern bool		recv_lsn_checks_on;
400 #ifdef UNIV_HOTBACKUP
401 /** TRUE when the redo log is being backed up */
402 extern bool		recv_is_making_a_backup;
403 #endif /* UNIV_HOTBACKUP */
404 
405 #ifndef UNIV_HOTBACKUP
406 /** Flag indicating if recv_writer thread is active. */
407 extern volatile bool	recv_writer_thread_active;
408 #endif /* !UNIV_HOTBACKUP */
409 
410 /** Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
411 times! */
412 #define RECV_PARSING_BUF_SIZE	(2 * 1024 * 1024)
413 
414 /** Size of block reads when the log groups are scanned forward to do a
415 roll-forward */
416 #define RECV_SCAN_SIZE		(4 * UNIV_PAGE_SIZE)
417 
418 /** This many frames must be left free in the buffer pool when we scan
419 the log and store the scanned log records in the buffer pool: we will
420 use these free frames to read in pages when we start applying the
421 log records to the database. */
422 extern ulint	recv_n_pool_free_frames;
423 
424 #ifndef UNIV_NONINL
425 #include "log0recv.ic"
426 #endif
427 
428 #endif
429