1 : /* Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
15 :
16 : #include "maria_def.h"
17 :
18 :
19 : /**
20 : @brief calculate crc of the page avoiding special values
21 :
22 : @param start The value to start CRC (we use page number here)
23 : @param data data pointer
24 : @param length length of the data
25 :
26 : @return crc of the page without special values
27 : */
28 :
29 : static uint32 maria_page_crc(uint32 start, uchar *data, uint length)
30 123301 : {
31 123301 : uint32 crc= crc32(start, data, length);
32 :
33 : /* we need this assert to get following comparison working */
34 : compile_time_assert(MARIA_NO_CRC_BITMAP_PAGE ==
35 : MARIA_NO_CRC_NORMAL_PAGE - 1 &&
36 : MARIA_NO_CRC_NORMAL_PAGE == 0xffffffff);
37 123301 : if (crc >= MARIA_NO_CRC_BITMAP_PAGE)
38 0 : crc= MARIA_NO_CRC_BITMAP_PAGE - 1;
39 :
40 123301 : return(crc);
41 : }
42 :
43 : /**
44 : @brief Maria pages read callback (checks the page CRC)
45 :
46 : @param page The page data to check
47 : @param page_no The page number (<offset>/<page length>)
48 : @param data_ptr pointer to MARIA_SHARE
49 : @param no_crc_val Value which means CRC absence
50 : (MARIA_NO_CRC_NORMAL_PAGE or MARIA_NO_CRC_BITMAP_PAGE)
51 : @param data_length length of data to calculate CRC
52 :
53 : @retval 0 OK
54 : @retval 1 Error
55 : */
56 :
57 : static my_bool maria_page_crc_check(uchar *page,
58 : pgcache_page_no_t page_no,
59 : MARIA_SHARE *share,
60 : uint32 no_crc_val,
61 : int data_length)
62 404166 : {
63 404166 : uint32 crc= uint4korr(page + share->block_size - CRC_SIZE), new_crc;
64 : my_bool res;
65 404166 : DBUG_ENTER("maria_page_crc_check");
66 :
67 404166 : DBUG_ASSERT((uint)data_length <= share->block_size - CRC_SIZE);
68 :
69 : /* we need this assert to get following comparison working */
70 : compile_time_assert(MARIA_NO_CRC_BITMAP_PAGE ==
71 : MARIA_NO_CRC_NORMAL_PAGE - 1 &&
72 : MARIA_NO_CRC_NORMAL_PAGE == 0xffffffff);
73 : /*
74 : If crc is no_crc_val then
75 : the page has no crc, so there is nothing to check.
76 : */
77 404166 : if (crc >= MARIA_NO_CRC_BITMAP_PAGE)
78 : {
79 327969 : DBUG_PRINT("info", ("No crc: %lu crc: %lu page: %lu ",
80 : (ulong) no_crc_val, (ulong) crc, (ulong) page_no));
81 327969 : if (crc != no_crc_val)
82 : {
83 0 : my_errno= HA_ERR_WRONG_CRC;
84 0 : DBUG_PRINT("error", ("Wrong no CRC value"));
85 0 : DBUG_RETURN(1);
86 : }
87 327969 : DBUG_RETURN(0);
88 : }
89 76197 : new_crc= maria_page_crc((uint32) page_no, page, data_length);
90 76197 : DBUG_ASSERT(new_crc != no_crc_val);
91 76197 : res= test(new_crc != crc);
92 76197 : if (res)
93 : {
94 : /*
95 : Bitmap pages may be totally zero filled in some cases.
96 : This happens when we get a crash after the pagecache has written
97 : out a page that is on a newly created bitmap page and we get
98 : a crash before the bitmap page is written out.
99 :
100 : We handle this case with the following logic:
101 : When reading, approve of bitmap pages where all bytes are zero
102 : (This is after all a bitmap pages where no data is reserved and
103 : the CRC will be corrected at next write)
104 : */
105 128 : if (no_crc_val == MARIA_NO_CRC_BITMAP_PAGE &&
106 : crc == 0 && _ma_check_if_zero(page, data_length))
107 : {
108 0 : DBUG_PRINT("warning", ("Found bitmap page that was not initialized"));
109 0 : DBUG_RETURN(0);
110 : }
111 :
112 128 : DBUG_PRINT("error", ("Page: %lu crc: %lu calculated crc: %lu",
113 : (ulong) page_no, (ulong) crc, (ulong) new_crc));
114 128 : my_errno= HA_ERR_WRONG_CRC;
115 : }
116 76197 : DBUG_RETURN(res);
117 : }
118 :
119 :
120 : /**
121 : @brief Maria pages write callback (sets the page CRC for data and index
122 : files)
123 :
124 : @param page The page data to set
125 : @param page_no The page number (<offset>/<page length>)
126 : @param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
127 :
128 : @retval 0 OK
129 : */
130 :
131 : my_bool maria_page_crc_set_normal(uchar *page,
132 : pgcache_page_no_t page_no,
133 : uchar *data_ptr)
134 34372 : {
135 34372 : MARIA_SHARE *share= (MARIA_SHARE *)data_ptr;
136 34372 : int data_length= share->block_size - CRC_SIZE;
137 34372 : uint32 crc= maria_page_crc((uint32) page_no, page, data_length);
138 34372 : DBUG_ENTER("maria_page_crc_set_normal");
139 34372 : DBUG_PRINT("info", ("Page %lu crc: %lu", (ulong) page_no, (ulong)crc));
140 :
141 : /* crc is on the stack so it is aligned, pagecache buffer is aligned, too */
142 34372 : int4store_aligned(page + data_length, crc);
143 34372 : DBUG_RETURN(0);
144 : }
145 :
146 :
147 : /**
148 : @brief Maria pages write callback (sets the page CRC for keys)
149 :
150 : @param page The page data to set
151 : @param page_no The page number (<offset>/<page length>)
152 : @param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
153 :
154 : @retval 0 OK
155 : */
156 :
157 : my_bool maria_page_crc_set_index(uchar *page,
158 : pgcache_page_no_t page_no,
159 : uchar *data_ptr)
160 12732 : {
161 12732 : MARIA_SHARE *share= (MARIA_SHARE *)data_ptr;
162 12732 : int data_length= _ma_get_page_used(share, page);
163 12732 : uint32 crc= maria_page_crc((uint32) page_no, page, data_length);
164 12732 : DBUG_ENTER("maria_page_crc_set_index");
165 12732 : DBUG_PRINT("info", ("Page %lu crc: %lu",
166 : (ulong) page_no, (ulong) crc));
167 12732 : DBUG_ASSERT((uint)data_length <= share->block_size - CRC_SIZE);
168 : /* crc is on the stack so it is aligned, pagecache buffer is aligned, too */
169 12732 : int4store_aligned(page + share->block_size - CRC_SIZE, crc);
170 12732 : DBUG_RETURN(0);
171 : }
172 :
173 :
174 : /* interface functions */
175 :
176 :
177 : /**
178 : @brief Maria pages read callback (checks the page CRC) for index/data pages
179 :
180 : @param page The page data to check
181 : @param page_no The page number (<offset>/<page length>)
182 : @param data_ptr Read callback data pointer (pointer to MARIA_SHARE)
183 :
184 : @retval 0 OK
185 : @retval 1 Error
186 : */
187 :
188 : my_bool maria_page_crc_check_data(uchar *page,
189 : pgcache_page_no_t page_no,
190 : uchar *data_ptr)
191 120960 : {
192 120960 : MARIA_SHARE *share= (MARIA_SHARE *)data_ptr;
193 120960 : return (maria_page_crc_check(page, (uint32) page_no, share,
194 : MARIA_NO_CRC_NORMAL_PAGE,
195 : share->block_size - CRC_SIZE));
196 : }
197 :
198 :
199 : /**
200 : @brief Maria pages read callback (checks the page CRC) for bitmap pages
201 :
202 : @param page The page data to check
203 : @param page_no The page number (<offset>/<page length>)
204 : @param data_ptr Read callback data pointer (pointer to MARIA_SHARE)
205 :
206 : @retval 0 OK
207 : @retval 1 Error
208 : */
209 :
210 : my_bool maria_page_crc_check_bitmap(uchar *page,
211 : pgcache_page_no_t page_no,
212 : uchar *data_ptr)
213 1729 : {
214 1729 : MARIA_SHARE *share= (MARIA_SHARE *)data_ptr;
215 1729 : return (maria_page_crc_check(page, (uint32) page_no, share,
216 : MARIA_NO_CRC_BITMAP_PAGE,
217 : share->block_size - CRC_SIZE));
218 : }
219 :
220 :
221 : /**
222 : @brief Maria pages read callback (checks the page CRC) for index pages
223 :
224 : @param page The page data to check
225 : @param page_no The page number (<offset>/<page length>)
226 : @param data_ptr Read callback data pointer (pointer to MARIA_SHARE)
227 :
228 : @retval 0 OK
229 : @retval 1 Error
230 : */
231 :
232 : my_bool maria_page_crc_check_index(uchar *page,
233 : pgcache_page_no_t page_no,
234 : uchar *data_ptr)
235 281477 : {
236 281477 : MARIA_SHARE *share= (MARIA_SHARE *)data_ptr;
237 281477 : uint length= _ma_get_page_used(share, page);
238 281477 : if (length > share->block_size - CRC_SIZE)
239 : {
240 0 : DBUG_PRINT("error", ("Wrong page length: %u", length));
241 0 : return (my_errno= HA_ERR_WRONG_CRC);
242 : }
243 281477 : return maria_page_crc_check(page, (uint32) page_no, share,
244 : MARIA_NO_CRC_NORMAL_PAGE,
245 : length);
246 : }
247 :
248 :
249 : /**
250 : @brief Maria pages dumme read callback for temporary tables
251 :
252 : @retval 0 OK
253 : @retval 1 Error
254 : */
255 :
256 : my_bool maria_page_crc_check_none(uchar *page __attribute__((unused)),
257 : pgcache_page_no_t page_no
258 : __attribute__((unused)),
259 : uchar *data_ptr __attribute__((unused)))
260 427228 : {
261 427228 : return 0;
262 : }
263 :
264 :
265 : /**
266 : @brief Maria pages write callback (sets the page filler for index/data)
267 :
268 : @param page The page data to set
269 : @param page_no The page number (<offset>/<page length>)
270 : @param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
271 :
272 : @retval 0 OK
273 : */
274 :
275 : my_bool maria_page_filler_set_normal(uchar *page,
276 : pgcache_page_no_t page_no
277 : __attribute__((unused)),
278 : uchar *data_ptr)
279 264821 : {
280 264821 : DBUG_ENTER("maria_page_filler_set_normal");
281 264821 : DBUG_ASSERT(page_no != 0); /* Catches some simple bugs */
282 264821 : int4store_aligned(page + ((MARIA_SHARE *)data_ptr)->block_size - CRC_SIZE,
283 : MARIA_NO_CRC_NORMAL_PAGE);
284 264821 : DBUG_RETURN(0);
285 : }
286 :
287 :
288 : /**
289 : @brief Maria pages write callback (sets the page filler for bitmap)
290 :
291 : @param page The page data to set
292 : @param page_no The page number (<offset>/<page length>)
293 : @param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
294 :
295 : @retval 0 OK
296 : */
297 :
298 : my_bool maria_page_filler_set_bitmap(uchar *page,
299 : pgcache_page_no_t page_no
300 : __attribute__((unused)),
301 : uchar *data_ptr)
302 163 : {
303 163 : DBUG_ENTER("maria_page_filler_set_bitmap");
304 163 : int4store_aligned(page + ((MARIA_SHARE *)data_ptr)->block_size - CRC_SIZE,
305 : MARIA_NO_CRC_BITMAP_PAGE);
306 163 : DBUG_RETURN(0);
307 : }
308 :
309 :
310 : /**
311 : @brief Maria pages dummy write callback for temporary tables
312 :
313 : @retval 0 OK
314 : */
315 :
316 : my_bool maria_page_filler_set_none(uchar *page __attribute__((unused)),
317 : pgcache_page_no_t page_no
318 : __attribute__((unused)),
319 : uchar *data_ptr __attribute__((unused)))
320 489399 : {
321 : #ifdef HAVE_purify
322 : int4store_aligned(page + ((MARIA_SHARE *)data_ptr)->block_size - CRC_SIZE,
323 : 0);
324 : #endif
325 489399 : return 0;
326 : }
327 :
328 :
329 : /**
330 : @brief Write failure callback (mark table as corrupted)
331 :
332 : @param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
333 : */
334 :
335 : void maria_page_write_failure(uchar* data_ptr)
336 0 : {
337 0 : maria_mark_crashed_share((MARIA_SHARE *)data_ptr);
338 : }
339 :
340 :
341 : /**
342 : @brief Maria flush log log if needed
343 :
344 : @param page The page data to set
345 : @param page_no The page number (<offset>/<page length>)
346 : @param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
347 :
348 : @retval 0 OK
349 : @retval 1 error
350 : */
351 :
352 : my_bool maria_flush_log_for_page(uchar *page,
353 : pgcache_page_no_t page_no
354 : __attribute__((unused)),
355 : uchar *data_ptr __attribute__((unused)))
356 144973 : {
357 : LSN lsn;
358 : #ifndef DBUG_OFF
359 144973 : const MARIA_SHARE *share= (MARIA_SHARE*) data_ptr;
360 : #endif
361 144973 : DBUG_ENTER("maria_flush_log_for_page");
362 : /* share is 0 here only in unittest */
363 144973 : DBUG_ASSERT(!share || (share->page_type == PAGECACHE_LSN_PAGE &&
364 : share->now_transactional));
365 144973 : lsn= lsn_korr(page);
366 144973 : if (translog_flush(lsn))
367 0 : DBUG_RETURN(1);
368 144973 : DBUG_RETURN(0);
369 : }
370 :
371 :
372 : my_bool maria_flush_log_for_page_none(uchar *page __attribute__((unused)),
373 : pgcache_page_no_t page_no
374 : __attribute__((unused)),
375 : uchar *data_ptr __attribute__((unused)))
376 655569 : {
377 655569 : return 0;
378 : }
|