Drizzled Public API Documentation

mtr0log.cc
1 /*****************************************************************************
2 
3 Copyright (C) 1995, 2009, Innobase Oy. 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., 51 Franklin
15 St, Fifth Floor, Boston, MA 02110-1301 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 (UNIV_LIKELY_NULL(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 (UNIV_LIKELY_NULL(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 (UNIV_LIKELY_NULL(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 (UNIV_LIKELY_NULL(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  byte* log_ptr;
255 
256  switch (type) {
257  case MLOG_1BYTE:
258  mach_write_to_1(ptr, val);
259  break;
260  case MLOG_2BYTES:
261  mach_write_to_2(ptr, val);
262  break;
263  case MLOG_4BYTES:
264  mach_write_to_4(ptr, val);
265  break;
266  default:
267  ut_error;
268  }
269 
270  log_ptr = mlog_open(mtr, 11 + 2 + 5);
271 
272  /* If no logging is requested, we may return now */
273  if (log_ptr == NULL) {
274 
275  return;
276  }
277 
278  log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr);
279 
280  mach_write_to_2(log_ptr, page_offset(ptr));
281  log_ptr += 2;
282 
283  log_ptr += mach_write_compressed(log_ptr, val);
284 
285  mlog_close(mtr, log_ptr);
286 }
287 
288 /********************************************************/
291 UNIV_INTERN
292 void
294 /*===========*/
295  byte* ptr,
296  ib_uint64_t val,
297  mtr_t* mtr)
298 {
299  byte* log_ptr;
300 
301  ut_ad(ptr && mtr);
302 
303  mach_write_to_8(ptr, val);
304 
305  log_ptr = mlog_open(mtr, 11 + 2 + 9);
306 
307  /* If no logging is requested, we may return now */
308  if (log_ptr == NULL) {
309 
310  return;
311  }
312 
314  log_ptr, mtr);
315 
316  mach_write_to_2(log_ptr, page_offset(ptr));
317  log_ptr += 2;
318 
319  log_ptr += mach_ull_write_compressed(log_ptr, val);
320 
321  mlog_close(mtr, log_ptr);
322 }
323 
324 #ifndef UNIV_HOTBACKUP
325 /********************************************************/
328 UNIV_INTERN
329 void
331 /*==============*/
332  byte* ptr,
333  const byte* str,
334  ulint len,
335  mtr_t* mtr)
336 {
337  ut_ad(ptr && mtr);
338  ut_a(len < UNIV_PAGE_SIZE);
339 
340  memcpy(ptr, str, len);
341 
342  mlog_log_string(ptr, len, mtr);
343 }
344 
345 /********************************************************/
348 UNIV_INTERN
349 void
351 /*============*/
352  byte* ptr,
353  ulint len,
354  mtr_t* mtr)
355 {
356  byte* log_ptr;
357 
358  ut_ad(ptr && mtr);
359  ut_ad(len <= UNIV_PAGE_SIZE);
360 
361  log_ptr = mlog_open(mtr, 30);
362 
363  /* If no logging is requested, we may return now */
364  if (log_ptr == NULL) {
365 
366  return;
367  }
368 
370  log_ptr, mtr);
371  mach_write_to_2(log_ptr, page_offset(ptr));
372  log_ptr += 2;
373 
374  mach_write_to_2(log_ptr, len);
375  log_ptr += 2;
376 
377  mlog_close(mtr, log_ptr);
378 
379  mlog_catenate_string(mtr, ptr, len);
380 }
381 #endif /* !UNIV_HOTBACKUP */
382 
383 /********************************************************/
386 UNIV_INTERN
387 byte*
389 /*==============*/
390  byte* ptr,
391  byte* end_ptr,
392  byte* page,
393  void* page_zip)
394 {
395  ulint offset;
396  ulint len;
397 
398  ut_a(!page || !page_zip || fil_page_get_type(page) != FIL_PAGE_INDEX);
399 
400  if (end_ptr < ptr + 4) {
401 
402  return(NULL);
403  }
404 
405  offset = mach_read_from_2(ptr);
406  ptr += 2;
407  len = mach_read_from_2(ptr);
408  ptr += 2;
409 
410  if (UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)
411  || UNIV_UNLIKELY(len + offset > UNIV_PAGE_SIZE)) {
412  recv_sys->found_corrupt_log = TRUE;
413 
414  return(NULL);
415  }
416 
417  if (end_ptr < ptr + len) {
418 
419  return(NULL);
420  }
421 
422  if (page) {
423  if (UNIV_LIKELY_NULL(page_zip)) {
424  memcpy(((page_zip_des_t*) page_zip)->data
425  + offset, ptr, len);
426  }
427  memcpy(page + offset, ptr, len);
428  }
429 
430  return(ptr + len);
431 }
432 
433 #ifndef UNIV_HOTBACKUP
434 /********************************************************/
438 UNIV_INTERN
439 byte*
441 /*======================*/
442  mtr_t* mtr,
443  const byte* rec,
444  dict_index_t* index,
445  byte type,
446  ulint size)
448 {
449  byte* log_ptr;
450  const byte* log_start;
451  const byte* log_end;
452 
453  ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
454 
455  if (!page_rec_is_comp(rec)) {
456  log_start = log_ptr = mlog_open(mtr, 11 + size);
457  if (!log_ptr) {
458  return(NULL); /* logging is disabled */
459  }
460  log_ptr = mlog_write_initial_log_record_fast(rec, type,
461  log_ptr, mtr);
462  log_end = log_ptr + 11 + size;
463  } else {
464  ulint i;
465  ulint n = dict_index_get_n_fields(index);
466  /* total size needed */
467  ulint total = 11 + size + (n + 2) * 2;
468  ulint alloc = total;
469  /* allocate at most DYN_ARRAY_DATA_SIZE at a time */
470  if (alloc > DYN_ARRAY_DATA_SIZE) {
471  alloc = DYN_ARRAY_DATA_SIZE;
472  }
473  log_start = log_ptr = mlog_open(mtr, alloc);
474  if (!log_ptr) {
475  return(NULL); /* logging is disabled */
476  }
477  log_end = log_ptr + alloc;
478  log_ptr = mlog_write_initial_log_record_fast(rec, type,
479  log_ptr, mtr);
480  mach_write_to_2(log_ptr, n);
481  log_ptr += 2;
482  mach_write_to_2(log_ptr,
484  log_ptr += 2;
485  for (i = 0; i < n; i++) {
486  dict_field_t* field;
487  const dict_col_t* col;
488  ulint len;
489 
490  field = dict_index_get_nth_field(index, i);
491  col = dict_field_get_col(field);
492  len = field->fixed_len;
493  ut_ad(len < 0x7fff);
494  if (len == 0
495  && (col->len > 255 || col->mtype == DATA_BLOB)) {
496  /* variable-length field
497  with maximum length > 255 */
498  len = 0x7fff;
499  }
500  if (col->prtype & DATA_NOT_NULL) {
501  len |= 0x8000;
502  }
503  if (log_ptr + 2 > log_end) {
504  mlog_close(mtr, log_ptr);
505  ut_a(total > (ulint) (log_ptr - log_start));
506  total -= log_ptr - log_start;
507  alloc = total;
508  if (alloc > DYN_ARRAY_DATA_SIZE) {
509  alloc = DYN_ARRAY_DATA_SIZE;
510  }
511  log_start = log_ptr = mlog_open(mtr, alloc);
512  if (!log_ptr) {
513  return(NULL); /* logging is disabled */
514  }
515  log_end = log_ptr + alloc;
516  }
517  mach_write_to_2(log_ptr, len);
518  log_ptr += 2;
519  }
520  }
521  if (size == 0) {
522  mlog_close(mtr, log_ptr);
523  log_ptr = NULL;
524  } else if (log_ptr + size > log_end) {
525  mlog_close(mtr, log_ptr);
526  log_ptr = mlog_open(mtr, size);
527  }
528  return(log_ptr);
529 }
530 #endif /* !UNIV_HOTBACKUP */
531 
532 /********************************************************/
535 UNIV_INTERN
536 byte*
538 /*=============*/
539  byte* ptr,
540  const byte* end_ptr,
541  ibool comp,
542  dict_index_t** index)
543 {
544  ulint i, n, n_uniq;
545  dict_table_t* table;
546  dict_index_t* ind;
547 
548  ut_ad(comp == FALSE || comp == TRUE);
549 
550  if (comp) {
551  if (end_ptr < ptr + 4) {
552  return(NULL);
553  }
554  n = mach_read_from_2(ptr);
555  ptr += 2;
556  n_uniq = mach_read_from_2(ptr);
557  ptr += 2;
558  ut_ad(n_uniq <= n);
559  if (end_ptr < ptr + n * 2) {
560  return(NULL);
561  }
562  } else {
563  n = n_uniq = 1;
564  }
565  table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n,
566  comp ? DICT_TF_COMPACT : 0);
567  ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY",
568  DICT_HDR_SPACE, 0, n);
569  ind->table = table;
570  ind->n_uniq = (unsigned int) n_uniq;
571  if (n_uniq != n) {
572  ut_a(n_uniq + DATA_ROLL_PTR <= n);
573  ind->type = DICT_CLUSTERED;
574  }
575  if (comp) {
576  for (i = 0; i < n; i++) {
577  ulint len = mach_read_from_2(ptr);
578  ptr += 2;
579  /* The high-order bit of len is the NOT NULL flag;
580  the rest is 0 or 0x7fff for variable-length fields,
581  and 1..0x7ffe for fixed-length fields. */
583  table, NULL, NULL,
584  ((len + 1) & 0x7fff) <= 1
585  ? DATA_BINARY : DATA_FIXBINARY,
586  len & 0x8000 ? DATA_NOT_NULL : 0,
587  len & 0x7fff);
588 
589  dict_index_add_col(ind, table,
590  dict_table_get_nth_col(table, i),
591  0);
592  }
593  dict_table_add_system_columns(table, table->heap);
594  if (n_uniq != n) {
595  /* Identify DB_TRX_ID and DB_ROLL_PTR in the index. */
596  ut_a(DATA_TRX_ID_LEN
597  == dict_index_get_nth_col(ind, DATA_TRX_ID - 1
598  + n_uniq)->len);
599  ut_a(DATA_ROLL_PTR_LEN
600  == dict_index_get_nth_col(ind, DATA_ROLL_PTR - 1
601  + n_uniq)->len);
602  ind->fields[DATA_TRX_ID - 1 + n_uniq].col
603  = &table->cols[n + DATA_TRX_ID];
604  ind->fields[DATA_ROLL_PTR - 1 + n_uniq].col
605  = &table->cols[n + DATA_ROLL_PTR];
606  }
607  }
608  /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
609  ind->cached = TRUE;
610  *index = ind;
611  return(ptr);
612 }
recv_sys_t * recv_sys
Definition: log0recv.cc:73
dict_col_t * cols
Definition: dict0mem.h:506
UNIV_INTERN byte * mlog_parse_nbytes(ulint type, byte *ptr, byte *end_ptr, byte *page, void *page_zip)
Definition: mtr0log.cc:140
#define FIL_PAGE_INDEX
Definition: fil0fil.h:173
dict_field_t * fields
Definition: dict0mem.h:371
UNIV_INLINE void mach_write_to_4(byte *b, ulint n)
UNIV_INLINE ulint dict_index_get_n_fields(const dict_index_t *index)
unsigned type
Definition: dict0mem.h:347
UNIV_INLINE void mlog_close(mtr_t *mtr, byte *ptr)
#define MLOG_1BYTE
Definition: mtr0mtr.h:73
UNIV_INTERN void mlog_write_string(byte *ptr, const byte *str, ulint len, mtr_t *mtr)
Definition: mtr0log.cc:330
UNIV_INLINE ibool dict_table_is_comp(const dict_table_t *table)
UNIV_INLINE void mach_write_to_8(byte *b, ib_uint64_t n)
UNIV_INTERN void mlog_write_ulint(byte *ptr, ulint val, byte type, mtr_t *mtr)
Definition: mtr0log.cc:247
UNIV_INTERN void dict_index_add_col(dict_index_t *index, const dict_table_t *table, dict_col_t *col, ulint prefix_len)
Definition: dict0dict.cc:1859
UNIV_INTERN dict_index_t * dict_mem_index_create(const char *table_name, const char *index_name, ulint space, ulint type, ulint n_fields)
Definition: dict0mem.cc:251
unsigned prtype
Definition: dict0mem.h:273
UNIV_INLINE ulint mtr_get_log_mode(mtr_t *mtr)
UNIV_INLINE byte * mach_ull_parse_compressed(byte *ptr, byte *end_ptr, ib_uint64_t *val)
UNIV_INLINE ulint mach_ull_write_compressed(byte *b, ib_uint64_t n)
#define MLOG_BIGGEST_TYPE
Definition: mtr0mtr.h:245
UNIV_INTERN byte * mlog_open_and_write_index(mtr_t *mtr, const byte *rec, dict_index_t *index, byte type, ulint size)
Definition: mtr0log.cc:440
mem_heap_t * heap
Definition: dict0mem.h:478
unsigned len
Definition: dict0mem.h:283
UNIV_INLINE const dict_col_t * dict_index_get_nth_col(const dict_index_t *index, ulint pos)
UNIV_INTERN byte * mlog_parse_string(byte *ptr, byte *end_ptr, byte *page, void *page_zip)
Definition: mtr0log.cc:388
ibool found_corrupt_log
Definition: log0recv.h:427
UNIV_INLINE ulint dict_index_get_n_unique_in_tree(const dict_index_t *index)
UNIV_INLINE void dyn_push_string(dyn_array_t *arr, const byte *str, ulint len)
#define MLOG_WRITE_STRING
Definition: mtr0mtr.h:154
dyn_array_t log
Definition: mtr0mtr.h:446
UNIV_INLINE byte * mlog_write_initial_log_record_fast(const byte *ptr, byte type, byte *log_ptr, mtr_t *mtr)
UNIV_INLINE ulint page_rec_is_comp(const rec_t *rec)
UNIV_INTERN void mlog_write_ull(byte *ptr, ib_uint64_t val, mtr_t *mtr)
Definition: mtr0log.cc:293
#define DICT_CLUSTERED
Definition: dict0mem.h:51
UNIV_INTERN byte * mach_parse_compressed(byte *ptr, byte *end_ptr, ulint *val)
Definition: mach0data.cc:38
UNIV_INTERN dict_table_t * dict_mem_table_create(const char *name, ulint space, ulint n_cols, ulint flags)
Definition: dict0mem.cc:59
#define MLOG_2BYTES
Definition: mtr0mtr.h:74
UNIV_INLINE ulint page_offset(const void *ptr) __attribute__((const ))
unsigned cached
Definition: dict0mem.h:363
UNIV_INTERN void mlog_catenate_string(mtr_t *mtr, const byte *str, ulint len)
Definition: mtr0log.cc:44
#define ut_a(EXPR)
Definition: ut0dbg.h:105
UNIV_INTERN void dict_table_add_system_columns(dict_table_t *table, mem_heap_t *heap)
Definition: dict0dict.cc:780
UNIV_INLINE const dict_col_t * dict_field_get_col(const dict_field_t *field)
dict_table_t * table
Definition: dict0mem.h:341
UNIV_INTERN ulint fil_page_get_type(const byte *page)
Definition: fil0fil.cc:4915
UNIV_INTERN void dict_mem_table_add_col(dict_table_t *table, mem_heap_t *heap, const char *name, ulint mtype, ulint prtype, ulint len)
Definition: dict0mem.cc:178
UNIV_INLINE void mach_write_to_1(byte *b, ulint n)
unsigned n_uniq
Definition: dict0mem.h:357
UNIV_INLINE byte * mlog_open(mtr_t *mtr, ulint size)
UNIV_INTERN void mlog_write_initial_log_record(const byte *ptr, byte type, mtr_t *mtr)
Definition: mtr0log.cc:68
#define MLOG_4BYTES
Definition: mtr0mtr.h:75
#define ut_ad(EXPR)
Definition: ut0dbg.h:127
#define DICT_TF_COMPACT
Definition: dict0mem.h:69
#define DYN_ARRAY_DATA_SIZE
Definition: dyn0dyn.h:42
#define ut_error
Definition: ut0dbg.h:115
UNIV_INLINE ulint mach_write_compressed(byte *b, ulint n)
UNIV_INLINE void mach_write_to_2(byte *b, ulint n)
UNIV_INTERN byte * mlog_parse_initial_log_record(byte *ptr, byte *end_ptr, byte *type, ulint *space, ulint *page_no)
Definition: mtr0log.cc:100
#define MLOG_8BYTES
Definition: mtr0mtr.h:76
UNIV_INTERN byte * mlog_parse_index(byte *ptr, const byte *end_ptr, ibool comp, dict_index_t **index)
Definition: mtr0log.cc:537
#define MLOG_SINGLE_REC_FLAG
Definition: mtr0mtr.h:62
dict_col_t * col
Definition: dict0mem.h:320
UNIV_INLINE ulint mach_read_from_2(const byte *b) __attribute__((nonnull
UNIV_INTERN void mlog_log_string(byte *ptr, ulint len, mtr_t *mtr)
Definition: mtr0log.cc:350
unsigned mtype
Definition: dict0mem.h:272
A block in a dynamically allocated array. NOTE! Do not access the fields of the struct directly: the ...
Definition: dyn0dyn.h:163
unsigned fixed_len
Definition: dict0mem.h:329