MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mtr0log.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************/
26 #include "mtr0log.h"
27 
28 #ifdef UNIV_NONINL
29 #include "mtr0log.ic"
30 #endif
31 
32 #include "buf0buf.h"
33 #include "dict0dict.h"
34 #include "log0recv.h"
35 #include "page0page.h"
36 
37 #ifndef UNIV_HOTBACKUP
38 # include "dict0boot.h"
39 
40 /********************************************************/
42 UNIV_INTERN
43 void
45 /*=================*/
46  mtr_t* mtr,
47  const byte* str,
48  ulint len)
49 {
50  dyn_array_t* mlog;
51 
52  if (mtr_get_log_mode(mtr) == MTR_LOG_NONE) {
53 
54  return;
55  }
56 
57  mlog = &(mtr->log);
58 
59  dyn_push_string(mlog, str, len);
60 }
61 
62 /********************************************************/
66 UNIV_INTERN
67 void
69 /*==========================*/
70  const byte* ptr,
73  byte type,
74  mtr_t* mtr)
75 {
76  byte* log_ptr;
77 
78  ut_ad(type <= MLOG_BIGGEST_TYPE);
79  ut_ad(type > MLOG_8BYTES);
80 
81  log_ptr = mlog_open(mtr, 11);
82 
83  /* If no logging is requested, we may return now */
84  if (log_ptr == NULL) {
85 
86  return;
87  }
88 
89  log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr);
90 
91  mlog_close(mtr, log_ptr);
92 }
93 #endif /* !UNIV_HOTBACKUP */
94 
95 /********************************************************/
98 UNIV_INTERN
99 byte*
101 /*==========================*/
102  byte* ptr,
103  byte* end_ptr,
104  byte* type,
105  ulint* space,
106  ulint* page_no)
107 {
108  if (end_ptr < ptr + 1) {
109 
110  return(NULL);
111  }
112 
113  *type = (byte)((ulint)*ptr & ~MLOG_SINGLE_REC_FLAG);
114  ut_ad(*type <= MLOG_BIGGEST_TYPE);
115 
116  ptr++;
117 
118  if (end_ptr < ptr + 2) {
119 
120  return(NULL);
121  }
122 
123  ptr = mach_parse_compressed(ptr, end_ptr, space);
124 
125  if (ptr == NULL) {
126 
127  return(NULL);
128  }
129 
130  ptr = mach_parse_compressed(ptr, end_ptr, page_no);
131 
132  return(ptr);
133 }
134 
135 /********************************************************/
138 UNIV_INTERN
139 byte*
141 /*==============*/
142  ulint type,
143  byte* ptr,
144  byte* end_ptr,
145  byte* page,
146  void* page_zip)
147 {
148  ulint offset;
149  ulint val;
150  ib_uint64_t dval;
151 
152  ut_a(type <= MLOG_8BYTES);
153  ut_a(!page || !page_zip || fil_page_get_type(page) != FIL_PAGE_INDEX);
154 
155  if (end_ptr < ptr + 2) {
156 
157  return(NULL);
158  }
159 
160  offset = mach_read_from_2(ptr);
161  ptr += 2;
162 
163  if (offset >= UNIV_PAGE_SIZE) {
164  recv_sys->found_corrupt_log = TRUE;
165 
166  return(NULL);
167  }
168 
169  if (type == MLOG_8BYTES) {
170  ptr = mach_ull_parse_compressed(ptr, end_ptr, &dval);
171 
172  if (ptr == NULL) {
173 
174  return(NULL);
175  }
176 
177  if (page) {
178  if (page_zip) {
180  (((page_zip_des_t*) page_zip)->data
181  + offset, dval);
182  }
183  mach_write_to_8(page + offset, dval);
184  }
185 
186  return(ptr);
187  }
188 
189  ptr = mach_parse_compressed(ptr, end_ptr, &val);
190 
191  if (ptr == NULL) {
192 
193  return(NULL);
194  }
195 
196  switch (type) {
197  case MLOG_1BYTE:
198  if (UNIV_UNLIKELY(val > 0xFFUL)) {
199  goto corrupt;
200  }
201  if (page) {
202  if (page_zip) {
204  (((page_zip_des_t*) page_zip)->data
205  + offset, val);
206  }
207  mach_write_to_1(page + offset, val);
208  }
209  break;
210  case MLOG_2BYTES:
211  if (UNIV_UNLIKELY(val > 0xFFFFUL)) {
212  goto corrupt;
213  }
214  if (page) {
215  if (page_zip) {
217  (((page_zip_des_t*) page_zip)->data
218  + offset, val);
219  }
220  mach_write_to_2(page + offset, val);
221  }
222  break;
223  case MLOG_4BYTES:
224  if (page) {
225  if (page_zip) {
227  (((page_zip_des_t*) page_zip)->data
228  + offset, val);
229  }
230  mach_write_to_4(page + offset, val);
231  }
232  break;
233  default:
234  corrupt:
235  recv_sys->found_corrupt_log = TRUE;
236  ptr = NULL;
237  }
238 
239  return(ptr);
240 }
241 
242 /********************************************************/
245 UNIV_INTERN
246 void
248 /*=============*/
249  byte* ptr,
250  ulint val,
251  byte type,
252  mtr_t* mtr)
253 {
254  switch (type) {
255  case MLOG_1BYTE:
256  mach_write_to_1(ptr, val);
257  break;
258  case MLOG_2BYTES:
259  mach_write_to_2(ptr, val);
260  break;
261  case MLOG_4BYTES:
262  mach_write_to_4(ptr, val);
263  break;
264  default:
265  ut_error;
266  }
267 
268  if (mtr != 0) {
269  byte* log_ptr = mlog_open(mtr, 11 + 2 + 5);
270 
271  /* If no logging is requested, we may return now */
272 
273  if (log_ptr != 0) {
274 
276  ptr, type, log_ptr, mtr);
277 
278  mach_write_to_2(log_ptr, page_offset(ptr));
279  log_ptr += 2;
280 
281  log_ptr += mach_write_compressed(log_ptr, val);
282 
283  mlog_close(mtr, log_ptr);
284  }
285  }
286 }
287 
288 /********************************************************/
291 UNIV_INTERN
292 void
294 /*===========*/
295  byte* ptr,
296  ib_uint64_t val,
297  mtr_t* mtr)
298 {
299  mach_write_to_8(ptr, val);
300 
301  if (mtr != 0) {
302  byte* log_ptr = mlog_open(mtr, 11 + 2 + 9);
303 
304  /* If no logging is requested, we may return now */
305  if (log_ptr != 0) {
306 
308  ptr, MLOG_8BYTES, log_ptr, mtr);
309 
310  mach_write_to_2(log_ptr, page_offset(ptr));
311  log_ptr += 2;
312 
313  log_ptr += mach_ull_write_compressed(log_ptr, val);
314 
315  mlog_close(mtr, log_ptr);
316  }
317  }
318 }
319 
320 #ifndef UNIV_HOTBACKUP
321 /********************************************************/
324 UNIV_INTERN
325 void
327 /*==============*/
328  byte* ptr,
329  const byte* str,
330  ulint len,
331  mtr_t* mtr)
332 {
333  ut_ad(ptr && mtr);
334  ut_a(len < UNIV_PAGE_SIZE);
335 
336  memcpy(ptr, str, len);
337 
338  mlog_log_string(ptr, len, mtr);
339 }
340 
341 /********************************************************/
344 UNIV_INTERN
345 void
347 /*============*/
348  byte* ptr,
349  ulint len,
350  mtr_t* mtr)
351 {
352  byte* log_ptr;
353 
354  ut_ad(ptr && mtr);
355  ut_ad(len <= UNIV_PAGE_SIZE);
356 
357  log_ptr = mlog_open(mtr, 30);
358 
359  /* If no logging is requested, we may return now */
360  if (log_ptr == NULL) {
361 
362  return;
363  }
364 
366  log_ptr, mtr);
367  mach_write_to_2(log_ptr, page_offset(ptr));
368  log_ptr += 2;
369 
370  mach_write_to_2(log_ptr, len);
371  log_ptr += 2;
372 
373  mlog_close(mtr, log_ptr);
374 
375  mlog_catenate_string(mtr, ptr, len);
376 }
377 #endif /* !UNIV_HOTBACKUP */
378 
379 /********************************************************/
382 UNIV_INTERN
383 byte*
385 /*==============*/
386  byte* ptr,
387  byte* end_ptr,
388  byte* page,
389  void* page_zip)
390 {
391  ulint offset;
392  ulint len;
393 
394  ut_a(!page || !page_zip || fil_page_get_type(page) != FIL_PAGE_INDEX);
395 
396  if (end_ptr < ptr + 4) {
397 
398  return(NULL);
399  }
400 
401  offset = mach_read_from_2(ptr);
402  ptr += 2;
403  len = mach_read_from_2(ptr);
404  ptr += 2;
405 
406  if (UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)
407  || UNIV_UNLIKELY(len + offset > UNIV_PAGE_SIZE)) {
408  recv_sys->found_corrupt_log = TRUE;
409 
410  return(NULL);
411  }
412 
413  if (end_ptr < ptr + len) {
414 
415  return(NULL);
416  }
417 
418  if (page) {
419  if (page_zip) {
420  memcpy(((page_zip_des_t*) page_zip)->data
421  + offset, ptr, len);
422  }
423  memcpy(page + offset, ptr, len);
424  }
425 
426  return(ptr + len);
427 }
428 
429 #ifndef UNIV_HOTBACKUP
430 /********************************************************/
434 UNIV_INTERN
435 byte*
437 /*======================*/
438  mtr_t* mtr,
439  const byte* rec,
440  const dict_index_t* index,
441  byte type,
442  ulint size)
445 {
446  byte* log_ptr;
447  const byte* log_start;
448  const byte* log_end;
449 
450  ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
451 
452  if (!page_rec_is_comp(rec)) {
453  log_start = log_ptr = mlog_open(mtr, 11 + size);
454  if (!log_ptr) {
455  return(NULL); /* logging is disabled */
456  }
457  log_ptr = mlog_write_initial_log_record_fast(rec, type,
458  log_ptr, mtr);
459  log_end = log_ptr + 11 + size;
460  } else {
461  ulint i;
462  ulint n = dict_index_get_n_fields(index);
463  /* total size needed */
464  ulint total = 11 + size + (n + 2) * 2;
465  ulint alloc = total;
466  /* allocate at most DYN_ARRAY_DATA_SIZE at a time */
467  if (alloc > DYN_ARRAY_DATA_SIZE) {
468  alloc = DYN_ARRAY_DATA_SIZE;
469  }
470  log_start = log_ptr = mlog_open(mtr, alloc);
471  if (!log_ptr) {
472  return(NULL); /* logging is disabled */
473  }
474  log_end = log_ptr + alloc;
475  log_ptr = mlog_write_initial_log_record_fast(rec, type,
476  log_ptr, mtr);
477  mach_write_to_2(log_ptr, n);
478  log_ptr += 2;
479  mach_write_to_2(log_ptr,
481  log_ptr += 2;
482  for (i = 0; i < n; i++) {
483  dict_field_t* field;
484  const dict_col_t* col;
485  ulint len;
486 
487  field = dict_index_get_nth_field(index, i);
488  col = dict_field_get_col(field);
489  len = field->fixed_len;
490  ut_ad(len < 0x7fff);
491  if (len == 0
492  && (col->len > 255 || col->mtype == DATA_BLOB)) {
493  /* variable-length field
494  with maximum length > 255 */
495  len = 0x7fff;
496  }
497  if (col->prtype & DATA_NOT_NULL) {
498  len |= 0x8000;
499  }
500  if (log_ptr + 2 > log_end) {
501  mlog_close(mtr, log_ptr);
502  ut_a(total > (ulint) (log_ptr - log_start));
503  total -= log_ptr - log_start;
504  alloc = total;
505  if (alloc > DYN_ARRAY_DATA_SIZE) {
506  alloc = DYN_ARRAY_DATA_SIZE;
507  }
508  log_start = log_ptr = mlog_open(mtr, alloc);
509  if (!log_ptr) {
510  return(NULL); /* logging is disabled */
511  }
512  log_end = log_ptr + alloc;
513  }
514  mach_write_to_2(log_ptr, len);
515  log_ptr += 2;
516  }
517  }
518  if (size == 0) {
519  mlog_close(mtr, log_ptr);
520  log_ptr = NULL;
521  } else if (log_ptr + size > log_end) {
522  mlog_close(mtr, log_ptr);
523  log_ptr = mlog_open(mtr, size);
524  }
525  return(log_ptr);
526 }
527 #endif /* !UNIV_HOTBACKUP */
528 
529 /********************************************************/
532 UNIV_INTERN
533 byte*
535 /*=============*/
536  byte* ptr,
537  const byte* end_ptr,
538  ibool comp,
539  dict_index_t** index)
540 {
541  ulint i, n, n_uniq;
543  dict_index_t* ind;
544 
545  ut_ad(comp == FALSE || comp == TRUE);
546 
547  if (comp) {
548  if (end_ptr < ptr + 4) {
549  return(NULL);
550  }
551  n = mach_read_from_2(ptr);
552  ptr += 2;
553  n_uniq = mach_read_from_2(ptr);
554  ptr += 2;
555  ut_ad(n_uniq <= n);
556  if (end_ptr < ptr + n * 2) {
557  return(NULL);
558  }
559  } else {
560  n = n_uniq = 1;
561  }
562  table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n,
563  comp ? DICT_TF_COMPACT : 0, 0);
564  ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY",
565  DICT_HDR_SPACE, 0, n);
566  ind->table = table;
567  ind->n_uniq = (unsigned int) n_uniq;
568  if (n_uniq != n) {
569  ut_a(n_uniq + DATA_ROLL_PTR <= n);
570  ind->type = DICT_CLUSTERED;
571  }
572  if (comp) {
573  for (i = 0; i < n; i++) {
574  ulint len = mach_read_from_2(ptr);
575  ptr += 2;
576  /* The high-order bit of len is the NOT NULL flag;
577  the rest is 0 or 0x7fff for variable-length fields,
578  and 1..0x7ffe for fixed-length fields. */
580  table, NULL, NULL,
581  ((len + 1) & 0x7fff) <= 1
582  ? DATA_BINARY : DATA_FIXBINARY,
583  len & 0x8000 ? DATA_NOT_NULL : 0,
584  len & 0x7fff);
585 
586  dict_index_add_col(ind, table,
587  dict_table_get_nth_col(table, i),
588  0);
589  }
590  dict_table_add_system_columns(table, table->heap);
591  if (n_uniq != n) {
592  /* Identify DB_TRX_ID and DB_ROLL_PTR in the index. */
593  ut_a(DATA_TRX_ID_LEN
594  == dict_index_get_nth_col(ind, DATA_TRX_ID - 1
595  + n_uniq)->len);
596  ut_a(DATA_ROLL_PTR_LEN
597  == dict_index_get_nth_col(ind, DATA_ROLL_PTR - 1
598  + n_uniq)->len);
599  ind->fields[DATA_TRX_ID - 1 + n_uniq].col
600  = &table->cols[n + DATA_TRX_ID];
601  ind->fields[DATA_ROLL_PTR - 1 + n_uniq].col
602  = &table->cols[n + DATA_ROLL_PTR];
603  }
604  }
605  /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
606  ind->cached = TRUE;
607  *index = ind;
608  return(ptr);
609 }