00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "mtr0log.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "mtr0log.ic"
00030 #endif
00031
00032 #include "buf0buf.h"
00033 #include "dict0dict.h"
00034 #include "log0recv.h"
00035 #include "page0page.h"
00036
00037 #ifndef UNIV_HOTBACKUP
00038 # include "dict0boot.h"
00039
00040
00042 UNIV_INTERN
00043 void
00044 mlog_catenate_string(
00045
00046 mtr_t* mtr,
00047 const byte* str,
00048 ulint len)
00049 {
00050 dyn_array_t* mlog;
00051
00052 if (mtr_get_log_mode(mtr) == MTR_LOG_NONE) {
00053
00054 return;
00055 }
00056
00057 mlog = &(mtr->log);
00058
00059 dyn_push_string(mlog, str, len);
00060 }
00061
00062
00066 UNIV_INTERN
00067 void
00068 mlog_write_initial_log_record(
00069
00070 const byte* ptr,
00073 byte type,
00074 mtr_t* mtr)
00075 {
00076 byte* log_ptr;
00077
00078 ut_ad(type <= MLOG_BIGGEST_TYPE);
00079 ut_ad(type > MLOG_8BYTES);
00080
00081 log_ptr = mlog_open(mtr, 11);
00082
00083
00084 if (log_ptr == NULL) {
00085
00086 return;
00087 }
00088
00089 log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr);
00090
00091 mlog_close(mtr, log_ptr);
00092 }
00093 #endif
00094
00095
00098 UNIV_INTERN
00099 byte*
00100 mlog_parse_initial_log_record(
00101
00102 byte* ptr,
00103 byte* end_ptr,
00104 byte* type,
00105 ulint* space,
00106 ulint* page_no)
00107 {
00108 if (end_ptr < ptr + 1) {
00109
00110 return(NULL);
00111 }
00112
00113 *type = (byte)((ulint)*ptr & ~MLOG_SINGLE_REC_FLAG);
00114 ut_ad(*type <= MLOG_BIGGEST_TYPE);
00115
00116 ptr++;
00117
00118 if (end_ptr < ptr + 2) {
00119
00120 return(NULL);
00121 }
00122
00123 ptr = mach_parse_compressed(ptr, end_ptr, space);
00124
00125 if (ptr == NULL) {
00126
00127 return(NULL);
00128 }
00129
00130 ptr = mach_parse_compressed(ptr, end_ptr, page_no);
00131
00132 return(ptr);
00133 }
00134
00135
00138 UNIV_INTERN
00139 byte*
00140 mlog_parse_nbytes(
00141
00142 ulint type,
00143 byte* ptr,
00144 byte* end_ptr,
00145 byte* page,
00146 void* page_zip)
00147 {
00148 ulint offset;
00149 ulint val;
00150 ib_uint64_t dval;
00151
00152 ut_a(type <= MLOG_8BYTES);
00153 ut_a(!page || !page_zip || fil_page_get_type(page) != FIL_PAGE_INDEX);
00154
00155 if (end_ptr < ptr + 2) {
00156
00157 return(NULL);
00158 }
00159
00160 offset = mach_read_from_2(ptr);
00161 ptr += 2;
00162
00163 if (offset >= UNIV_PAGE_SIZE) {
00164 recv_sys->found_corrupt_log = TRUE;
00165
00166 return(NULL);
00167 }
00168
00169 if (type == MLOG_8BYTES) {
00170 ptr = mach_ull_parse_compressed(ptr, end_ptr, &dval);
00171
00172 if (ptr == NULL) {
00173
00174 return(NULL);
00175 }
00176
00177 if (page) {
00178 if (UNIV_LIKELY_NULL(page_zip)) {
00179 mach_write_to_8
00180 (((page_zip_des_t*) page_zip)->data
00181 + offset, dval);
00182 }
00183 mach_write_to_8(page + offset, dval);
00184 }
00185
00186 return(ptr);
00187 }
00188
00189 ptr = mach_parse_compressed(ptr, end_ptr, &val);
00190
00191 if (ptr == NULL) {
00192
00193 return(NULL);
00194 }
00195
00196 switch (type) {
00197 case MLOG_1BYTE:
00198 if (UNIV_UNLIKELY(val > 0xFFUL)) {
00199 goto corrupt;
00200 }
00201 if (page) {
00202 if (UNIV_LIKELY_NULL(page_zip)) {
00203 mach_write_to_1
00204 (((page_zip_des_t*) page_zip)->data
00205 + offset, val);
00206 }
00207 mach_write_to_1(page + offset, val);
00208 }
00209 break;
00210 case MLOG_2BYTES:
00211 if (UNIV_UNLIKELY(val > 0xFFFFUL)) {
00212 goto corrupt;
00213 }
00214 if (page) {
00215 if (UNIV_LIKELY_NULL(page_zip)) {
00216 mach_write_to_2
00217 (((page_zip_des_t*) page_zip)->data
00218 + offset, val);
00219 }
00220 mach_write_to_2(page + offset, val);
00221 }
00222 break;
00223 case MLOG_4BYTES:
00224 if (page) {
00225 if (UNIV_LIKELY_NULL(page_zip)) {
00226 mach_write_to_4
00227 (((page_zip_des_t*) page_zip)->data
00228 + offset, val);
00229 }
00230 mach_write_to_4(page + offset, val);
00231 }
00232 break;
00233 default:
00234 corrupt:
00235 recv_sys->found_corrupt_log = TRUE;
00236 ptr = NULL;
00237 }
00238
00239 return(ptr);
00240 }
00241
00242
00245 UNIV_INTERN
00246 void
00247 mlog_write_ulint(
00248
00249 byte* ptr,
00250 ulint val,
00251 byte type,
00252 mtr_t* mtr)
00253 {
00254 byte* log_ptr;
00255
00256 switch (type) {
00257 case MLOG_1BYTE:
00258 mach_write_to_1(ptr, val);
00259 break;
00260 case MLOG_2BYTES:
00261 mach_write_to_2(ptr, val);
00262 break;
00263 case MLOG_4BYTES:
00264 mach_write_to_4(ptr, val);
00265 break;
00266 default:
00267 ut_error;
00268 }
00269
00270 log_ptr = mlog_open(mtr, 11 + 2 + 5);
00271
00272
00273 if (log_ptr == NULL) {
00274
00275 return;
00276 }
00277
00278 log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr);
00279
00280 mach_write_to_2(log_ptr, page_offset(ptr));
00281 log_ptr += 2;
00282
00283 log_ptr += mach_write_compressed(log_ptr, val);
00284
00285 mlog_close(mtr, log_ptr);
00286 }
00287
00288
00291 UNIV_INTERN
00292 void
00293 mlog_write_ull(
00294
00295 byte* ptr,
00296 ib_uint64_t val,
00297 mtr_t* mtr)
00298 {
00299 byte* log_ptr;
00300
00301 ut_ad(ptr && mtr);
00302
00303 mach_write_to_8(ptr, val);
00304
00305 log_ptr = mlog_open(mtr, 11 + 2 + 9);
00306
00307
00308 if (log_ptr == NULL) {
00309
00310 return;
00311 }
00312
00313 log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_8BYTES,
00314 log_ptr, mtr);
00315
00316 mach_write_to_2(log_ptr, page_offset(ptr));
00317 log_ptr += 2;
00318
00319 log_ptr += mach_ull_write_compressed(log_ptr, val);
00320
00321 mlog_close(mtr, log_ptr);
00322 }
00323
00324 #ifndef UNIV_HOTBACKUP
00325
00328 UNIV_INTERN
00329 void
00330 mlog_write_string(
00331
00332 byte* ptr,
00333 const byte* str,
00334 ulint len,
00335 mtr_t* mtr)
00336 {
00337 ut_ad(ptr && mtr);
00338 ut_a(len < UNIV_PAGE_SIZE);
00339
00340 memcpy(ptr, str, len);
00341
00342 mlog_log_string(ptr, len, mtr);
00343 }
00344
00345
00348 UNIV_INTERN
00349 void
00350 mlog_log_string(
00351
00352 byte* ptr,
00353 ulint len,
00354 mtr_t* mtr)
00355 {
00356 byte* log_ptr;
00357
00358 ut_ad(ptr && mtr);
00359 ut_ad(len <= UNIV_PAGE_SIZE);
00360
00361 log_ptr = mlog_open(mtr, 30);
00362
00363
00364 if (log_ptr == NULL) {
00365
00366 return;
00367 }
00368
00369 log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_WRITE_STRING,
00370 log_ptr, mtr);
00371 mach_write_to_2(log_ptr, page_offset(ptr));
00372 log_ptr += 2;
00373
00374 mach_write_to_2(log_ptr, len);
00375 log_ptr += 2;
00376
00377 mlog_close(mtr, log_ptr);
00378
00379 mlog_catenate_string(mtr, ptr, len);
00380 }
00381 #endif
00382
00383
00386 UNIV_INTERN
00387 byte*
00388 mlog_parse_string(
00389
00390 byte* ptr,
00391 byte* end_ptr,
00392 byte* page,
00393 void* page_zip)
00394 {
00395 ulint offset;
00396 ulint len;
00397
00398 ut_a(!page || !page_zip || fil_page_get_type(page) != FIL_PAGE_INDEX);
00399
00400 if (end_ptr < ptr + 4) {
00401
00402 return(NULL);
00403 }
00404
00405 offset = mach_read_from_2(ptr);
00406 ptr += 2;
00407 len = mach_read_from_2(ptr);
00408 ptr += 2;
00409
00410 if (UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)
00411 || UNIV_UNLIKELY(len + offset) > UNIV_PAGE_SIZE) {
00412 recv_sys->found_corrupt_log = TRUE;
00413
00414 return(NULL);
00415 }
00416
00417 if (end_ptr < ptr + len) {
00418
00419 return(NULL);
00420 }
00421
00422 if (page) {
00423 if (UNIV_LIKELY_NULL(page_zip)) {
00424 memcpy(((page_zip_des_t*) page_zip)->data
00425 + offset, ptr, len);
00426 }
00427 memcpy(page + offset, ptr, len);
00428 }
00429
00430 return(ptr + len);
00431 }
00432
00433 #ifndef UNIV_HOTBACKUP
00434
00438 UNIV_INTERN
00439 byte*
00440 mlog_open_and_write_index(
00441
00442 mtr_t* mtr,
00443 const byte* rec,
00444 dict_index_t* index,
00445 byte type,
00446 ulint size)
00448 {
00449 byte* log_ptr;
00450 const byte* log_start;
00451 const byte* log_end;
00452
00453 ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
00454
00455 if (!page_rec_is_comp(rec)) {
00456 log_start = log_ptr = mlog_open(mtr, 11 + size);
00457 if (!log_ptr) {
00458 return(NULL);
00459 }
00460 log_ptr = mlog_write_initial_log_record_fast(rec, type,
00461 log_ptr, mtr);
00462 log_end = log_ptr + 11 + size;
00463 } else {
00464 ulint i;
00465 ulint n = dict_index_get_n_fields(index);
00466
00467 ulint total = 11 + size + (n + 2) * 2;
00468 ulint alloc = total;
00469
00470 if (alloc > DYN_ARRAY_DATA_SIZE) {
00471 alloc = DYN_ARRAY_DATA_SIZE;
00472 }
00473 log_start = log_ptr = mlog_open(mtr, alloc);
00474 if (!log_ptr) {
00475 return(NULL);
00476 }
00477 log_end = log_ptr + alloc;
00478 log_ptr = mlog_write_initial_log_record_fast(rec, type,
00479 log_ptr, mtr);
00480 mach_write_to_2(log_ptr, n);
00481 log_ptr += 2;
00482 mach_write_to_2(log_ptr,
00483 dict_index_get_n_unique_in_tree(index));
00484 log_ptr += 2;
00485 for (i = 0; i < n; i++) {
00486 dict_field_t* field;
00487 const dict_col_t* col;
00488 ulint len;
00489
00490 field = dict_index_get_nth_field(index, i);
00491 col = dict_field_get_col(field);
00492 len = field->fixed_len;
00493 ut_ad(len < 0x7fff);
00494 if (len == 0
00495 && (col->len > 255 || col->mtype == DATA_BLOB)) {
00496
00497
00498 len = 0x7fff;
00499 }
00500 if (col->prtype & DATA_NOT_NULL) {
00501 len |= 0x8000;
00502 }
00503 if (log_ptr + 2 > log_end) {
00504 mlog_close(mtr, log_ptr);
00505 ut_a(total > (ulint) (log_ptr - log_start));
00506 total -= log_ptr - log_start;
00507 alloc = total;
00508 if (alloc > DYN_ARRAY_DATA_SIZE) {
00509 alloc = DYN_ARRAY_DATA_SIZE;
00510 }
00511 log_start = log_ptr = mlog_open(mtr, alloc);
00512 if (!log_ptr) {
00513 return(NULL);
00514 }
00515 log_end = log_ptr + alloc;
00516 }
00517 mach_write_to_2(log_ptr, len);
00518 log_ptr += 2;
00519 }
00520 }
00521 if (size == 0) {
00522 mlog_close(mtr, log_ptr);
00523 log_ptr = NULL;
00524 } else if (log_ptr + size > log_end) {
00525 mlog_close(mtr, log_ptr);
00526 log_ptr = mlog_open(mtr, size);
00527 }
00528 return(log_ptr);
00529 }
00530 #endif
00531
00532
00535 UNIV_INTERN
00536 byte*
00537 mlog_parse_index(
00538
00539 byte* ptr,
00540 const byte* end_ptr,
00541 ibool comp,
00542 dict_index_t** index)
00543 {
00544 ulint i, n, n_uniq;
00545 dict_table_t* table;
00546 dict_index_t* ind;
00547
00548 ut_ad(comp == FALSE || comp == TRUE);
00549
00550 if (comp) {
00551 if (end_ptr < ptr + 4) {
00552 return(NULL);
00553 }
00554 n = mach_read_from_2(ptr);
00555 ptr += 2;
00556 n_uniq = mach_read_from_2(ptr);
00557 ptr += 2;
00558 ut_ad(n_uniq <= n);
00559 if (end_ptr < ptr + n * 2) {
00560 return(NULL);
00561 }
00562 } else {
00563 n = n_uniq = 1;
00564 }
00565 table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n,
00566 comp ? DICT_TF_COMPACT : 0);
00567 ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY",
00568 DICT_HDR_SPACE, 0, n);
00569 ind->table = table;
00570 ind->n_uniq = (unsigned int) n_uniq;
00571 if (n_uniq != n) {
00572 ut_a(n_uniq + DATA_ROLL_PTR <= n);
00573 ind->type = DICT_CLUSTERED;
00574 }
00575 if (comp) {
00576 for (i = 0; i < n; i++) {
00577 ulint len = mach_read_from_2(ptr);
00578 ptr += 2;
00579
00580
00581
00582 dict_mem_table_add_col(
00583 table, NULL, NULL,
00584 ((len + 1) & 0x7fff) <= 1
00585 ? DATA_BINARY : DATA_FIXBINARY,
00586 len & 0x8000 ? DATA_NOT_NULL : 0,
00587 len & 0x7fff);
00588
00589 dict_index_add_col(ind, table,
00590 dict_table_get_nth_col(table, i),
00591 0);
00592 }
00593 dict_table_add_system_columns(table, table->heap);
00594 if (n_uniq != n) {
00595
00596 ut_a(DATA_TRX_ID_LEN
00597 == dict_index_get_nth_col(ind, DATA_TRX_ID - 1
00598 + n_uniq)->len);
00599 ut_a(DATA_ROLL_PTR_LEN
00600 == dict_index_get_nth_col(ind, DATA_ROLL_PTR - 1
00601 + n_uniq)->len);
00602 ind->fields[DATA_TRX_ID - 1 + n_uniq].col
00603 = &table->cols[n + DATA_TRX_ID];
00604 ind->fields[DATA_ROLL_PTR - 1 + n_uniq].col
00605 = &table->cols[n + DATA_ROLL_PTR];
00606 }
00607 }
00608
00609 ind->cached = TRUE;
00610 *index = ind;
00611 return(ptr);
00612 }