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 "log0types.h"
42 #include "log0log.h"
43 #include "mtr0types.h"
44 #include "ut0new.h"
45 
46 #include <list>
47 #include <vector>
48 
49 /** Check the 4-byte checksum to the trailer checksum field of a log
50 block.
51 @param[in]	log block
52 @return whether the checksum matches */
53 bool
54 log_block_checksum_is_ok(
55 	const byte*	block)	/*!< in: pointer to a log block */
56 	MY_ATTRIBUTE((warn_unused_result));
57 
58 /*******************************************************//**
59 Calculates the new value for lsn when more data is added to the log. */
60 
61 lsn_t
62 recv_calc_lsn_on_data_add(
63 /*======================*/
64 	lsn_t		lsn,	/*!< in: old lsn */
65 	ib_uint64_t	len);	/*!< in: this many bytes of data is
66 				added, log block headers not included */
67 
68 #ifdef UNIV_HOTBACKUP
69 extern bool	recv_replay_file_ops;
70 
71 /*******************************************************************//**
72 Reads the checkpoint info needed in hot backup.
73 @return TRUE if success */
74 ibool
75 recv_read_checkpoint_info_for_backup(
76 /*=================================*/
77 	const byte*	hdr,	/*!< in: buffer containing the log group
78 				header */
79 	lsn_t*		lsn,	/*!< out: checkpoint lsn */
80 	lsn_t*		offset,	/*!< out: checkpoint offset in the log group */
81 	lsn_t*		cp_no,	/*!< out: checkpoint number */
82 	lsn_t*		first_header_lsn)
83 				/*!< out: lsn of of the start of the
84 				first log file */
85 	MY_ATTRIBUTE((nonnull));
86 /*******************************************************************//**
87 Scans the log segment and n_bytes_scanned is set to the length of valid
88 log scanned. */
89 void
90 recv_scan_log_seg_for_backup(
91 /*=========================*/
92 	byte*		buf,		/*!< in: buffer containing log data */
93 	ulint		buf_len,	/*!< in: data length in that buffer */
94 	lsn_t*		scanned_lsn,	/*!< in/out: lsn of buffer start,
95 					we return scanned lsn */
96 	ulint*		scanned_checkpoint_no,
97 					/*!< in/out: 4 lowest bytes of the
98 					highest scanned checkpoint number so
99 					far */
100 	ulint*		n_bytes_scanned);/*!< out: how much we were able to
101 					scan, smaller than buf_len if log
102 					data ended here */
103 #endif /* UNIV_HOTBACKUP */
104 /*******************************************************************//**
105 Returns TRUE if recovery is currently running.
106 @return recv_recovery_on */
107 UNIV_INLINE
108 bool
109 recv_recovery_is_on(void);
110 /*=====================*/
111 /************************************************************************//**
112 Applies the hashed log records to the page, if the page lsn is less than the
113 lsn of a log record. This can be called when a buffer page has just been
114 read in, or also for a page already in the buffer pool. */
115 void
116 recv_recover_page_func(
117 /*===================*/
118 #ifndef UNIV_HOTBACKUP
119 	ibool		just_read_in,
120 				/*!< in: TRUE if the i/o handler calls
121 				this for a freshly read page */
122 #endif /* !UNIV_HOTBACKUP */
123 	buf_block_t*	block);	/*!< in/out: buffer block */
124 #ifndef UNIV_HOTBACKUP
125 /** Wrapper for recv_recover_page_func().
126 Applies the hashed log records to the page, if the page lsn is less than the
127 lsn of a log record. This can be called when a buffer page has just been
128 read in, or also for a page already in the buffer pool.
129 @param jri in: TRUE if just read in (the i/o handler calls this for
130 a freshly read page)
131 @param block in/out: the buffer block
132 */
133 # define recv_recover_page(jri, block)	recv_recover_page_func(jri, block)
134 #else /* !UNIV_HOTBACKUP */
135 /** Wrapper for recv_recover_page_func().
136 Applies the hashed log records to the page, if the page lsn is less than the
137 lsn of a log record. This can be called when a buffer page has just been
138 read in, or also for a page already in the buffer pool.
139 @param jri in: TRUE if just read in (the i/o handler calls this for
140 a freshly read page)
141 @param block in/out: the buffer block
142 */
143 # define recv_recover_page(jri, block)	recv_recover_page_func(block)
144 #endif /* !UNIV_HOTBACKUP */
145 /** Start recovering from a redo log checkpoint.
146 @see recv_recovery_from_checkpoint_finish
147 @param[in]	flush_lsn	FIL_PAGE_FILE_FLUSH_LSN
148 of first system tablespace page
149 @return error code or DB_SUCCESS */
150 dberr_t
151 recv_recovery_from_checkpoint_start(
152 	lsn_t	flush_lsn);
153 /** Complete recovery from a checkpoint. */
154 void
155 recv_recovery_from_checkpoint_finish(void);
156 /********************************************************//**
157 Initiates the rollback of active transactions. */
158 void
159 recv_recovery_rollback_active(void);
160 /*===============================*/
161 
162 /** Tries to parse a single log record.
163 @param[out]	type		log record type
164 @param[in]	ptr		pointer to a buffer
165 @param[in]	end_ptr		end of the buffer
166 @param[out]	space_id	tablespace identifier
167 @param[out]	page_no		page number
168 @param[in]	apply		whether to apply MLOG_FILE_* records
169 @param[out]	body		start of log record body
170 @return length of the record, or 0 if the record was not complete */
171 
172 ulint
173 recv_parse_log_rec(
174 	mlog_id_t*	type,
175 	byte*		ptr,
176 	byte*		end_ptr,
177 	ulint*		space,
178 	ulint*		page_no,
179 	bool		apply,
180 	byte**		body);
181 
182 /******************************************************//**
183 Resets the logs. The contents of log files will be lost! */
184 void
185 recv_reset_logs(
186 /*============*/
187 	lsn_t		lsn);		/*!< in: reset to this lsn
188 					rounded up to be divisible by
189 					OS_FILE_LOG_BLOCK_SIZE, after
190 					which we add
191 					LOG_BLOCK_HDR_SIZE */
192 #ifdef UNIV_HOTBACKUP
193 /******************************************************//**
194 Creates new log files after a backup has been restored. */
195 void
196 recv_reset_log_files_for_backup(
197 /*============================*/
198 	const char*	log_dir,	/*!< in: log file directory path */
199 	ulint		n_log_files,	/*!< in: number of log files */
200 	lsn_t		log_file_size,	/*!< in: log file size */
201 	lsn_t		lsn);		/*!< in: new start lsn, must be
202 					divisible by OS_FILE_LOG_BLOCK_SIZE */
203 #endif /* UNIV_HOTBACKUP */
204 /********************************************************//**
205 Creates the recovery system. */
206 void
207 recv_sys_create(void);
208 /*=================*/
209 /**********************************************************//**
210 Release recovery system mutexes. */
211 void
212 recv_sys_close(void);
213 /*================*/
214 /********************************************************//**
215 Frees the recovery system memory. */
216 void
217 recv_sys_mem_free(void);
218 /*===================*/
219 /********************************************************//**
220 Inits the recovery system for a recovery operation. */
221 void
222 recv_sys_init(
223 /*==========*/
224 	ulint	available_memory);	/*!< in: available memory in bytes */
225 #ifndef UNIV_HOTBACKUP
226 /********************************************************//**
227 Frees the recovery system. */
228 void
229 recv_sys_debug_free(void);
230 /*=====================*/
231 /********************************************************//**
232 Reset the state of the recovery system variables. */
233 void
234 recv_sys_var_init(void);
235 /*===================*/
236 #endif /* !UNIV_HOTBACKUP */
237 /*******************************************************************//**
238 Empties the hash table of stored log records, applying them to appropriate
239 pages. */
240 void
241 recv_apply_hashed_log_recs(
242 /*=======================*/
243 	ibool	allow_ibuf);	/*!< in: if TRUE, also ibuf operations are
244 				allowed during the application; if FALSE,
245 				no ibuf operations are allowed, and after
246 				the application all file pages are flushed to
247 				disk and invalidated in buffer pool: this
248 				alternative means that no new log records
249 				can be generated during the application */
250 
251 /*********************************************************************//**
252 Gets the hashed file address struct for a page.
253 @return file address struct, NULL if not found from the hash table */
254 
255 recv_addr_t*
256 recv_get_fil_addr_struct(
257 /*=====================*/
258 	ulint	space,	/*!< in: space id */
259 	ulint	page_no)/*!< in: page number */
260 	MY_ATTRIBUTE((warn_unused_result));
261 
262 #ifdef UNIV_HOTBACKUP
263 /*******************************************************************//**
264 Applies log records in the hash table to a backup. */
265 void
266 recv_apply_log_recs_for_backup(void);
267 /*================================*/
268 #endif /* UNIV_HOTBACKUP */
269 
270 /** Block of log record data */
271 struct recv_data_t{
272 	recv_data_t*	next;	/*!< pointer to the next block or NULL */
273 				/*!< the log record data is stored physically
274 				immediately after this struct, max amount
275 				RECV_DATA_BLOCK_SIZE bytes of it */
276 };
277 
278 /** Stored log record struct */
279 struct recv_t{
280 	mlog_id_t	type;	/*!< log record type */
281 	ulint		len;	/*!< log record body length in bytes */
282 	recv_data_t*	data;	/*!< chain of blocks containing the log record
283 				body */
284 	lsn_t		start_lsn;/*!< start lsn of the log segment written by
285 				the mtr which generated this log record: NOTE
286 				that this is not necessarily the start lsn of
287 				this log record */
288 	lsn_t		end_lsn;/*!< end lsn of the log segment written by
289 				the mtr which generated this log record: NOTE
290 				that this is not necessarily the end lsn of
291 				this log record */
292 	UT_LIST_NODE_T(recv_t)
293 			rec_list;/*!< list of log records for this page */
294 };
295 
296 /** States of recv_addr_t */
297 enum recv_addr_state {
298 	/** not yet processed */
299 	RECV_NOT_PROCESSED,
300 	/** page is being read */
301 	RECV_BEING_READ,
302 	/** log records are being applied on the page */
303 	RECV_BEING_PROCESSED,
304 	/** log records have been applied on the page */
305 	RECV_PROCESSED,
306 	/** log records have been discarded because the tablespace
307 	does not exist */
308 	RECV_DISCARDED
309 };
310 
311 /** Hashed page file address struct */
312 struct recv_addr_t{
313 	enum recv_addr_state state;
314 				/*!< recovery state of the page */
315 	unsigned	space:32;/*!< space id */
316 	unsigned	page_no:32;/*!< page number */
317 	UT_LIST_BASE_NODE_T(recv_t)
318 			rec_list;/*!< list of log records for this page */
319 	hash_node_t	addr_hash;/*!< hash node in the hash bucket chain */
320 };
321 
322 struct recv_dblwr_t {
323 	/** Add a page frame to the doublewrite recovery buffer. */
addrecv_dblwr_t324 	void add(byte* page) {
325 		pages.push_back(page);
326 	}
327 
328 	/** Add a page frame to sys_list and the global list of double
329 	write pages. The separate list is used to decrypt doublewrite
330 	buffer pages of encrypted system tablespace
331 	@param[in]	page	doublwrite buffer page */
add_to_sysrecv_dblwr_t332 	void add_to_sys(byte* page) {
333 		sys_pages.push_back(page);
334 		pages.push_back(page);
335 	}
336 
337 	/** Find a doublewrite copy of a page.
338 	@param[in]	space_id	tablespace identifier
339 	@param[in]	page_no		page number
340 	@return	page frame
341 	@retval NULL if no page was found */
342 	const byte* find_page(ulint space_id, ulint page_no);
343 
344 	typedef std::list<byte*, ut_allocator<byte*> >	list;
345 
346 	/** Recovered doublewrite buffer page frames */
347 	list	pages;
348 
349 	/** Pages from system tablespace doublewrite buffer.
350 	If encrypted, these pages should be decrypted with system tablespace
351 	encryption key. Other pages from parallel double write buffer should
352 	be decrypted with their respective tablespace encryption key */
353 	list 	sys_pages;
354 
355 	/** Decrypt double write buffer pages if system tablespace is
356 	encrypted. This function process only pages from sys_pages list.
357 	Other pages from parallel doublewrite buffer will be decrypted after
358 	tablespace objects are loaded. */
359 	void decrypt_sys_dblwr_pages();
360 };
361 
362 /* Recovery encryption information */
363 typedef	struct recv_encryption {
364 	ulint		space_id;	/*!< the page number */
365 	byte*		key;		/*!< encryption key */
366 	byte*		iv;		/*!< encryption iv */
367 } recv_encryption_t;
368 
369 typedef std::vector<recv_encryption_t, ut_allocator<recv_encryption_t> >
370 		encryption_list_t;
371 
372 /** Recovery system data structure */
373 struct recv_sys_t{
374 #ifndef UNIV_HOTBACKUP
375 	ib_mutex_t		mutex;	/*!< mutex protecting the fields apply_log_recs,
376 				n_addrs, and the state field in each recv_addr
377 				struct */
378 	os_event_t		flush_start;/*!< event to acticate
379 				page cleaner threads */
380 	os_event_t		flush_end;/*!< event to signal that the page
381 				cleaner has finished the request */
382 #endif /* !UNIV_HOTBACKUP */
383 	ibool		apply_log_recs;
384 				/*!< this is TRUE when log rec application to
385 				pages is allowed; this flag tells the
386 				i/o-handler if it should do log record
387 				application */
388 	ibool		apply_batch_on;
389 				/*!< this is TRUE when a log rec application
390 				batch is running */
391 	byte*		last_block;
392 				/*!< possible incomplete last recovered log
393 				block */
394 	byte*		last_block_buf_start;
395 				/*!< the nonaligned start address of the
396 				preceding buffer */
397 	byte*		buf;	/*!< buffer for parsing log records */
398 	ulint		len;	/*!< amount of data in buf */
399 	lsn_t		parse_start_lsn;
400 				/*!< this is the lsn from which we were able to
401 				start parsing log records and adding them to
402 				the hash table; zero if a suitable
403 				start point not found yet */
404 	lsn_t		scanned_lsn;
405 				/*!< the log data has been scanned up to this
406 				lsn */
407 	ulint		scanned_checkpoint_no;
408 				/*!< the log data has been scanned up to this
409 				checkpoint number (lowest 4 bytes) */
410 	ulint		recovered_offset;
411 				/*!< start offset of non-parsed log records in
412 				buf */
413 	lsn_t		recovered_lsn;
414 				/*!< the log records have been parsed up to
415 				this lsn */
416 	bool		found_corrupt_log;
417 				/*!< set when finding a corrupt log
418 				block or record, or there is a log
419 				parsing buffer overflow */
420 	bool		found_corrupt_fs;
421 				/*!< set when an inconsistency with
422 				the file system contents is detected
423 				during log scan or apply */
424 	lsn_t		mlog_checkpoint_lsn;
425 				/*!< the LSN of a MLOG_CHECKPOINT
426 				record, or 0 if none was parsed */
427 	mem_heap_t*	heap;	/*!< memory heap of log records and file
428 				addresses*/
429 	hash_table_t*	addr_hash;/*!< hash table of file addresses of pages */
430 	ulint		n_addrs;/*!< number of not processed hashed file
431 				addresses in the hash table */
432 
433 	recv_dblwr_t	dblwr;
434 
435 	encryption_list_t*	/*!< Encryption information list */
436 			encryption_list;
437 
set_corrupt_logrecv_sys_t438 	void set_corrupt_log() {
439 		found_corrupt_log = true;
440 	}
441 };
442 
443 /** The recovery system */
444 extern recv_sys_t*	recv_sys;
445 
446 /** TRUE when applying redo log records during crash recovery; FALSE
447 otherwise.  Note that this is FALSE while a background thread is
448 rolling back incomplete transactions. */
449 extern volatile bool	recv_recovery_on;
450 /** If the following is TRUE, the buffer pool file pages must be invalidated
451 after recovery and no ibuf operations are allowed; this becomes TRUE if
452 the log record hash table becomes too full, and log records must be merged
453 to file pages already before the recovery is finished: in this case no
454 ibuf operations are allowed, as they could modify the pages read in the
455 buffer pool before the pages have been recovered to the up-to-date state.
456 
457 TRUE means that recovery is running and no operations on the log files
458 are allowed yet: the variable name is misleading. */
459 extern bool		recv_no_ibuf_operations;
460 /** TRUE when recv_init_crash_recovery() has been called. */
461 extern bool		recv_needed_recovery;
462 #ifdef UNIV_DEBUG
463 /** TRUE if writing to the redo log (mtr_commit) is forbidden.
464 Protected by log_sys->mutex. */
465 extern bool		recv_no_log_write;
466 #endif /* UNIV_DEBUG */
467 
468 /** TRUE if buf_page_is_corrupted() should check if the log sequence
469 number (FIL_PAGE_LSN) is in the future.  Initially FALSE, and set by
470 recv_recovery_from_checkpoint_start(). */
471 extern bool		recv_lsn_checks_on;
472 #ifdef UNIV_HOTBACKUP
473 /** TRUE when the redo log is being backed up */
474 extern bool		recv_is_making_a_backup;
475 #endif /* UNIV_HOTBACKUP */
476 
477 /** Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
478 times! */
479 #define RECV_PARSING_BUF_SIZE	(2 * 1024 * 1024)
480 
481 /** Size of block reads when the log groups are scanned forward to do a
482 roll-forward */
483 #define RECV_SCAN_SIZE		(4 * UNIV_PAGE_SIZE)
484 
485 /** This many frames must be left free in the buffer pool when we scan
486 the log and store the scanned log records in the buffer pool: we will
487 use these free frames to read in pages when we start applying the
488 log records to the database. */
489 extern ulint	recv_n_pool_free_frames;
490 
491 #ifndef UNIV_NONINL
492 #include "log0recv.ic"
493 #endif
494 
495 #endif
496