1/* Copyright (C) 2006,2007,2008 MySQL AB
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
15
16/*
17 Q: Why isn't ma_recovery_util.c simply moved to ma_recovery.c ?
18
19 A: ma_recovery.c, because it invokes objects from ma_check.c (like
20 maria_chk_init()) causes the following problem:
21 if a source file a.c of a program invokes a function defined in
22 ma_recovery.c, then a.o depends on ma_recovery.o which depends on
23 ma_check.o: linker thus brings in ma_check.o. That brings in the
24 dependencies of ma_check.o which are definitions of _ma_check_print_info()
25 etc; if a.o does not define them then the ones of ha_maria.o are used
26 i.e. ha_maria.o is linked into the program, and this brings in dependencies
27 of ha_maria.o on mysqld.o into the program's linking which thus fails, as
28 the program is not linked with mysqld.o.
29 Thus, while several functions defined in ma_recovery.c could be useful to
30 other files, they cannot be used by them.
31 So we are going to gradually move a great share of ma_recovery.c's exported
32 functions into the present file, to isolate the problematic components and
33 avoid the problem.
34*/
35
36#include "maria_def.h"
37
38HASH all_dirty_pages;
39struct st_dirty_page /* used only in the REDO phase */
40{
41 uint64 file_and_page_id;
42 LSN rec_lsn;
43};
44/*
45 LSN after which dirty pages list does not apply. Can be slightly before
46 when ma_checkpoint_execute() started.
47*/
48LSN checkpoint_start= LSN_IMPOSSIBLE;
49
50/** @todo looks like duplicate of recovery_message_printed */
51my_bool procent_printed;
52FILE *tracef; /**< trace file for debugging */
53
54
55/** @brief Prints to a trace file if it is not NULL */
56void tprint(FILE *trace_file __attribute__ ((unused)),
57 const char *format __attribute__ ((unused)), ...)
58{
59 va_list args;
60#ifndef DBUG_OFF
61 {
62 char buff[1024], *end;
63 va_start(args, format);
64 vsnprintf(buff, sizeof(buff)-1, format, args);
65 if (*(end= strend(buff)) == '\n')
66 *end= 0; /* Don't print end \n */
67 DBUG_PRINT("info", ("%s", buff));
68 va_end(args);
69 }
70#endif
71 va_start(args, format);
72 if (trace_file != NULL)
73 {
74 if (procent_printed)
75 {
76 procent_printed= 0;
77 fputc('\n', trace_file);
78 }
79 vfprintf(trace_file, format, args);
80 }
81 va_end(args);
82}
83
84
85void eprint(FILE *trace_file __attribute__ ((unused)),
86 const char *format __attribute__ ((unused)), ...)
87{
88 va_list args;
89 va_start(args, format);
90 DBUG_PRINT("error", ("%s", format));
91 if (!trace_file)
92 trace_file= stderr;
93
94 if (procent_printed)
95 {
96 /* In silent mode, print on another line than the 0% 10% 20% line */
97 procent_printed= 0;
98 fputc('\n', trace_file);
99 }
100 vfprintf(trace_file , format, args);
101 fputc('\n', trace_file);
102 if (trace_file != stderr)
103 {
104 va_start(args, format);
105 my_printv_error(HA_ERR_INITIALIZATION, format, MYF(0), args);
106 }
107 va_end(args);
108 fflush(trace_file);
109}
110
111
112/**
113 Tells if the dirty pages list found in checkpoint record allows to ignore a
114 REDO for a certain page.
115
116 @param shortid short id of the table
117 @param lsn REDO record's LSN
118 @param page page number
119 @param index TRUE if index page, FALSE if data page
120*/
121
122my_bool _ma_redo_not_needed_for_page(uint16 shortid, LSN lsn,
123 pgcache_page_no_t page,
124 my_bool index)
125{
126 if (cmp_translog_addr(lsn, checkpoint_start) < 0)
127 {
128 /*
129 64-bit key is formed like this:
130 Most significant byte: 0 if data page, 1 if index page
131 Next 2 bytes: table's short id
132 Next 5 bytes: page number
133 */
134 char llbuf[22];
135 uint64 file_and_page_id=
136 (((uint64)((index << 16) | shortid)) << 40) | page;
137 struct st_dirty_page *dirty_page= (struct st_dirty_page *)
138 my_hash_search(&all_dirty_pages,
139 (uchar *)&file_and_page_id, sizeof(file_and_page_id));
140 DBUG_PRINT("info", ("page %lld in dirty pages list: %d",
141 (ulonglong) page,
142 dirty_page != NULL));
143 if ((dirty_page == NULL) ||
144 cmp_translog_addr(lsn, dirty_page->rec_lsn) < 0)
145 {
146 tprint(tracef, ", ignoring page %s because of dirty_pages list\n",
147 llstr((ulonglong) page, llbuf));
148 return TRUE;
149 }
150 }
151 return FALSE;
152}
153