#include "log0recv.h"#include "mem0mem.h"#include "buf0buf.h"#include "buf0flu.h"#include "buf0rea.h"#include "srv0srv.h"#include "srv0start.h"#include "mtr0mtr.h"#include "mtr0log.h"#include "page0page.h"#include "page0cur.h"#include "btr0btr.h"#include "btr0cur.h"#include "ibuf0ibuf.h"#include "trx0undo.h"#include "trx0rec.h"#include "trx0roll.h"#include "dict0boot.h"#include "fil0fil.h"Include dependency graph for log0recv.c:

Go to the source code of this file.
| #define RECV_DATA_BLOCK_SIZE (MEM_MAX_ALLOC_IN_BUF - sizeof(recv_data_t)) |
Definition at line 46 of file log0recv.c.
Referenced by recv_add_to_hash_table(), recv_data_copy_to_buf(), and recv_recover_page().
| #define recv_is_making_a_backup FALSE |
| #define RECV_READ_AHEAD_AREA 32 |
| static ibool log_block_checksum_is_ok_or_old_format | ( | byte * | block | ) | [static] |
Definition at line 627 of file log0recv.c.
References FALSE, log_block_calc_checksum(), log_block_get_checksum(), log_block_get_hdr_no(), and TRUE.
Referenced by recv_scan_log_recs(), and recv_scan_log_seg_for_backup().
00629 : TRUE if ok, or if the log block may be in the 00630 format of InnoDB version < 3.23.52 */ 00631 byte* block) /* in: pointer to a log block */ 00632 { 00633 #ifdef UNIV_LOG_DEBUG 00634 return(TRUE); 00635 #endif /* UNIV_LOG_DEBUG */ 00636 if (log_block_calc_checksum(block) == log_block_get_checksum(block)) { 00637 00638 return(TRUE); 00639 } 00640 00641 if (log_block_get_hdr_no(block) == log_block_get_checksum(block)) { 00642 00643 /* We assume the log block is in the format of 00644 InnoDB version < 3.23.52 and the block is ok */ 00645 /* 00646 fprintf(stderr, 00647 "InnoDB: Scanned old format < InnoDB-3.23.52 log block number %lu\n", 00648 log_block_get_hdr_no(block)); 00649 */ 00650 return(TRUE); 00651 } 00652 00653 return(FALSE); 00654 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void recv_add_to_hash_table | ( | byte | type, | |
| ulint | space, | |||
| ulint | page_no, | |||
| byte * | body, | |||
| byte * | rec_end, | |||
| dulint | start_lsn, | |||
| dulint | end_lsn | |||
| ) | [static] |
Definition at line 966 of file log0recv.c.
References recv_sys_struct::addr_hash, recv_struct::data, recv_struct::end_lsn, fil_tablespace_deleted_or_being_deleted_in_mem(), HASH_INSERT, recv_sys_struct::heap, recv_struct::len, mem_heap_alloc(), recv_sys_struct::n_addrs, NULL, recv_addr_struct::page_no, recv_addr_struct::rec_list, RECV_DATA_BLOCK_SIZE, recv_fold(), recv_get_fil_addr_struct(), RECV_NOT_PROCESSED, recv_sys, recv_addr_struct::space, recv_struct::start_lsn, recv_addr_struct::state, recv_struct::type, UT_LIST_ADD_LAST, UT_LIST_INIT, and ut_memcpy().
Referenced by recv_parse_log_recs().
00968 : log record type */ 00969 ulint space, /* in: space id */ 00970 ulint page_no, /* in: page number */ 00971 byte* body, /* in: log record body */ 00972 byte* rec_end, /* in: log record end */ 00973 dulint start_lsn, /* in: start lsn of the mtr */ 00974 dulint end_lsn) /* in: end lsn of the mtr */ 00975 { 00976 recv_t* recv; 00977 ulint len; 00978 recv_data_t* recv_data; 00979 recv_data_t** prev_field; 00980 recv_addr_t* recv_addr; 00981 00982 if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) { 00983 /* The tablespace does not exist any more: do not store the 00984 log record */ 00985 00986 return; 00987 } 00988 00989 len = rec_end - body; 00990 00991 recv = mem_heap_alloc(recv_sys->heap, sizeof(recv_t)); 00992 recv->type = type; 00993 recv->len = rec_end - body; 00994 recv->start_lsn = start_lsn; 00995 recv->end_lsn = end_lsn; 00996 00997 recv_addr = recv_get_fil_addr_struct(space, page_no); 00998 00999 if (recv_addr == NULL) { 01000 recv_addr = mem_heap_alloc(recv_sys->heap, 01001 sizeof(recv_addr_t)); 01002 recv_addr->space = space; 01003 recv_addr->page_no = page_no; 01004 recv_addr->state = RECV_NOT_PROCESSED; 01005 01006 UT_LIST_INIT(recv_addr->rec_list); 01007 01008 HASH_INSERT(recv_addr_t, addr_hash, recv_sys->addr_hash, 01009 recv_fold(space, page_no), recv_addr); 01010 recv_sys->n_addrs++; 01011 01012 /* fprintf(stderr, "Inserting log rec for space %lu, page %lu\n", 01013 space, page_no); */ 01014 } 01015 01016 UT_LIST_ADD_LAST(rec_list, recv_addr->rec_list, recv); 01017 01018 prev_field = &(recv->data); 01019 01020 /* Store the log record body in chunks of less than UNIV_PAGE_SIZE: 01021 recv_sys->heap grows into the buffer pool, and bigger chunks could not 01022 be allocated */ 01023 01024 while (rec_end > body) { 01025 01026 len = rec_end - body; 01027 01028 if (len > RECV_DATA_BLOCK_SIZE) { 01029 len = RECV_DATA_BLOCK_SIZE; 01030 } 01031 01032 recv_data = mem_heap_alloc(recv_sys->heap, 01033 sizeof(recv_data_t) + len); 01034 *prev_field = recv_data; 01035 01036 ut_memcpy(((byte*)recv_data) + sizeof(recv_data_t), body, len); 01037 01038 prev_field = &(recv_data->next); 01039 01040 body += len; 01041 } 01042 01043 *prev_field = NULL; 01044 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void recv_apply_hashed_log_recs | ( | ibool | allow_ibuf | ) |
Definition at line 1324 of file log0recv.c.
References recv_sys_struct::addr_hash, recv_sys_struct::apply_batch_on, recv_sys_struct::apply_log_recs, buf_flush_batch(), BUF_FLUSH_LIST, buf_flush_wait_batch_end(), buf_page_get, buf_page_peek(), buf_pool_invalidate(), FALSE, HASH_GET_FIRST, hash_get_n_cells(), HASH_GET_NEXT, log_sys, mtr_commit(), mtr_start(), log_struct::mutex, recv_sys_struct::mutex, mutex_enter, mutex_exit(), recv_sys_struct::n_addrs, os_thread_sleep(), page, recv_addr_struct::page_no, page_t, recv_no_ibuf_operations, RECV_NOT_PROCESSED, recv_read_in_area(), recv_recover_page(), recv_sys, recv_sys_empty_hash(), RW_X_LATCH, recv_addr_struct::space, recv_addr_struct::state, SYNC_NO_ORDER_CHECK, TRUE, ut_a, ut_ad, ut_dulint_max, and ut_print_timestamp().
Referenced by log_checkpoint(), log_preflush_pool_modified_pages(), recv_recovery_from_checkpoint_finish(), and recv_scan_log_recs().
01326 : if TRUE, also ibuf operations are 01327 allowed during the application; if FALSE, 01328 no ibuf operations are allowed, and after 01329 the application all file pages are flushed to 01330 disk and invalidated in buffer pool: this 01331 alternative means that no new log records 01332 can be generated during the application; 01333 the caller must in this case own the log 01334 mutex */ 01335 { 01336 recv_addr_t* recv_addr; 01337 page_t* page; 01338 ulint i; 01339 ulint space; 01340 ulint page_no; 01341 ulint n_pages; 01342 ibool has_printed = FALSE; 01343 mtr_t mtr; 01344 loop: 01345 mutex_enter(&(recv_sys->mutex)); 01346 01347 if (recv_sys->apply_batch_on) { 01348 01349 mutex_exit(&(recv_sys->mutex)); 01350 01351 os_thread_sleep(500000); 01352 01353 goto loop; 01354 } 01355 01356 #ifdef UNIV_SYNC_DEBUG 01357 ut_ad(!allow_ibuf == mutex_own(&log_sys->mutex)); 01358 #endif /* UNIV_SYNC_DEBUG */ 01359 if (!allow_ibuf) { 01360 recv_no_ibuf_operations = TRUE; 01361 } 01362 01363 recv_sys->apply_log_recs = TRUE; 01364 recv_sys->apply_batch_on = TRUE; 01365 01366 for (i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) { 01367 01368 recv_addr = HASH_GET_FIRST(recv_sys->addr_hash, i); 01369 01370 while (recv_addr) { 01371 space = recv_addr->space; 01372 page_no = recv_addr->page_no; 01373 01374 if (recv_addr->state == RECV_NOT_PROCESSED) { 01375 if (!has_printed) { 01376 ut_print_timestamp(stderr); 01377 fputs( 01378 " InnoDB: Starting an apply batch of log records to the database...\n" 01379 "InnoDB: Progress in percents: ",stderr); 01380 has_printed = TRUE; 01381 } 01382 01383 mutex_exit(&(recv_sys->mutex)); 01384 01385 if (buf_page_peek(space, page_no)) { 01386 01387 mtr_start(&mtr); 01388 01389 page = buf_page_get(space, page_no, 01390 RW_X_LATCH, &mtr); 01391 01392 #ifdef UNIV_SYNC_DEBUG 01393 buf_page_dbg_add_level(page, 01394 SYNC_NO_ORDER_CHECK); 01395 #endif /* UNIV_SYNC_DEBUG */ 01396 recv_recover_page(FALSE, FALSE, page, 01397 space, page_no); 01398 mtr_commit(&mtr); 01399 } else { 01400 recv_read_in_area(space, page_no); 01401 } 01402 01403 mutex_enter(&(recv_sys->mutex)); 01404 } 01405 01406 recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); 01407 } 01408 01409 if (has_printed 01410 && (i * 100) / hash_get_n_cells(recv_sys->addr_hash) 01411 != ((i + 1) * 100) 01412 / hash_get_n_cells(recv_sys->addr_hash)) { 01413 01414 fprintf(stderr, "%lu ", 01415 (ulong) ((i * 100) / hash_get_n_cells(recv_sys->addr_hash))); 01416 } 01417 } 01418 01419 /* Wait until all the pages have been processed */ 01420 01421 while (recv_sys->n_addrs != 0) { 01422 01423 mutex_exit(&(recv_sys->mutex)); 01424 01425 os_thread_sleep(500000); 01426 01427 mutex_enter(&(recv_sys->mutex)); 01428 } 01429 01430 if (has_printed) { 01431 01432 fprintf(stderr, "\n"); 01433 } 01434 01435 if (!allow_ibuf) { 01436 /* Flush all the file pages to disk and invalidate them in 01437 the buffer pool */ 01438 01439 mutex_exit(&(recv_sys->mutex)); 01440 mutex_exit(&(log_sys->mutex)); 01441 01442 n_pages = buf_flush_batch(BUF_FLUSH_LIST, ULINT_MAX, 01443 ut_dulint_max); 01444 ut_a(n_pages != ULINT_UNDEFINED); 01445 01446 buf_flush_wait_batch_end(BUF_FLUSH_LIST); 01447 01448 buf_pool_invalidate(); 01449 01450 mutex_enter(&(log_sys->mutex)); 01451 mutex_enter(&(recv_sys->mutex)); 01452 01453 recv_no_ibuf_operations = FALSE; 01454 } 01455 01456 recv_sys->apply_log_recs = FALSE; 01457 recv_sys->apply_batch_on = FALSE; 01458 01459 recv_sys_empty_hash(); 01460 01461 if (has_printed) { 01462 fprintf(stderr, "InnoDB: Apply batch completed\n"); 01463 } 01464 01465 mutex_exit(&(recv_sys->mutex)); 01466 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void recv_apply_log_recs_for_backup | ( | void | ) |
Definition at line 1476 of file log0recv.c.
References recv_sys_struct::addr_hash, recv_sys_struct::apply_batch_on, recv_sys_struct::apply_log_recs, buf_block_align(), buf_flush_init_for_writing(), buf_frame_alloc(), buf_page_init_for_backup_restore(), DB_SUCCESS, error, exit, FALSE, fil_extend_space_to_desired_size(), fil_io(), FIL_PAGE_LSN, fil_tablespace_exists_in_mem(), hash_get_n_cells(), HASH_GET_NEXT, hash_get_nth_cell(), mach_read_from_8(), recv_sys_struct::n_addrs, hash_cell_struct::node, NULL, OS_FILE_READ, OS_FILE_WRITE, page, recv_addr_struct::page_no, recv_backup_application_page, RECV_PROCESSED, recv_recover_page(), recv_sys, recv_addr_struct::space, recv_addr_struct::state, TRUE, UNIV_PAGE_SIZE, and ut_a.
01478 { 01479 recv_addr_t* recv_addr; 01480 ulint n_hash_cells; 01481 byte* page; 01482 ulint actual_size; 01483 ibool success; 01484 ulint error; 01485 ulint i; 01486 01487 recv_sys->apply_log_recs = TRUE; 01488 recv_sys->apply_batch_on = TRUE; 01489 01490 if (recv_backup_application_page == NULL) { 01491 recv_backup_application_page = buf_frame_alloc(); 01492 } 01493 01494 page = recv_backup_application_page; 01495 01496 fputs( 01497 "InnoDB: Starting an apply batch of log records to the database...\n" 01498 "InnoDB: Progress in percents: ", stderr); 01499 01500 n_hash_cells = hash_get_n_cells(recv_sys->addr_hash); 01501 01502 for (i = 0; i < n_hash_cells; i++) { 01503 /* The address hash table is externally chained */ 01504 recv_addr = hash_get_nth_cell(recv_sys->addr_hash, i)->node; 01505 01506 while (recv_addr != NULL) { 01507 01508 if (!fil_tablespace_exists_in_mem(recv_addr->space)) { 01509 /* 01510 fprintf(stderr, 01511 "InnoDB: Warning: cannot apply log record to tablespace %lu page %lu,\n" 01512 "InnoDB: because tablespace with that id does not exist.\n", 01513 recv_addr->space, recv_addr->page_no); 01514 */ 01515 recv_addr->state = RECV_PROCESSED; 01516 01517 ut_a(recv_sys->n_addrs); 01518 recv_sys->n_addrs--; 01519 01520 goto skip_this_recv_addr; 01521 } 01522 01523 /* We simulate a page read made by the buffer pool, to 01524 make sure the recovery apparatus works ok, for 01525 example, the buf_frame_align() function. We must init 01526 the block corresponding to buf_pool->frame_zero 01527 (== page). */ 01528 01529 buf_page_init_for_backup_restore(recv_addr->space, 01530 recv_addr->page_no, 01531 buf_block_align(page)); 01532 01533 /* Extend the tablespace's last file if the page_no 01534 does not fall inside its bounds; we assume the last 01535 file is auto-extending, and ibbackup copied the file 01536 when it still was smaller */ 01537 01538 success = fil_extend_space_to_desired_size( 01539 &actual_size, 01540 recv_addr->space, 01541 recv_addr->page_no + 1); 01542 if (!success) { 01543 fprintf(stderr, 01544 "InnoDB: Fatal error: cannot extend" 01545 " tablespace %lu to hold %lu pages\n", 01546 recv_addr->space, recv_addr->page_no); 01547 01548 exit(1); 01549 } 01550 01551 /* Read the page from the tablespace file using the 01552 fil0fil.c routines */ 01553 01554 error = fil_io(OS_FILE_READ, TRUE, recv_addr->space, 01555 recv_addr->page_no, 0, UNIV_PAGE_SIZE, 01556 page, NULL); 01557 if (error != DB_SUCCESS) { 01558 fprintf(stderr, 01559 "InnoDB: Fatal error: cannot read from tablespace" 01560 " %lu page number %lu\n", 01561 (ulong) recv_addr->space, 01562 (ulong) recv_addr->page_no); 01563 01564 exit(1); 01565 } 01566 01567 /* Apply the log records to this page */ 01568 recv_recover_page(TRUE, FALSE, page, recv_addr->space, 01569 recv_addr->page_no); 01570 01571 /* Write the page back to the tablespace file using the 01572 fil0fil.c routines */ 01573 01574 buf_flush_init_for_writing(page, 01575 mach_read_from_8(page + FIL_PAGE_LSN), 01576 recv_addr->space, recv_addr->page_no); 01577 01578 error = fil_io(OS_FILE_WRITE, TRUE, recv_addr->space, 01579 recv_addr->page_no, 0, UNIV_PAGE_SIZE, 01580 page, NULL); 01581 skip_this_recv_addr: 01582 recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); 01583 } 01584 01585 if ((100 * i) / n_hash_cells 01586 != (100 * (i + 1)) / n_hash_cells) { 01587 fprintf(stderr, "%lu ", 01588 (ulong) ((100 * i) / n_hash_cells)); 01589 fflush(stderr); 01590 } 01591 } 01592 01593 recv_sys_empty_hash(); 01594 }
Here is the call graph for this function:

Definition at line 1873 of file log0recv.c.
References LOG_BLOCK_HDR_SIZE, LOG_BLOCK_TRL_SIZE, OS_FILE_LOG_BLOCK_SIZE, ut_ad, ut_dulint_add(), and ut_dulint_get_low().
Referenced by recv_parse_log_recs().
01875 : old lsn */ 01876 ulint len) /* in: this many bytes of data is added, log block 01877 headers not included */ 01878 { 01879 ulint frag_len; 01880 ulint lsn_len; 01881 01882 frag_len = (ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE) 01883 - LOG_BLOCK_HDR_SIZE; 01884 ut_ad(frag_len < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE 01885 - LOG_BLOCK_TRL_SIZE); 01886 lsn_len = len + ((len + frag_len) 01887 / (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE 01888 - LOG_BLOCK_TRL_SIZE)) 01889 * (LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE); 01890 01891 return(ut_dulint_add(lsn, lsn_len)); 01892 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool recv_check_cp_is_consistent | ( | byte * | buf | ) | [static] |
Definition at line 433 of file log0recv.c.
References FALSE, LOG_CHECKPOINT_CHECKSUM_1, LOG_CHECKPOINT_CHECKSUM_2, LOG_CHECKPOINT_LSN, mach_read_from_4(), TRUE, and ut_fold_binary().
Referenced by recv_find_max_checkpoint(), and recv_read_cp_info_for_backup().
00435 : TRUE if ok */ 00436 byte* buf) /* in: buffer containing checkpoint info */ 00437 { 00438 ulint fold; 00439 00440 fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1); 00441 00442 if ((fold & 0xFFFFFFFFUL) != mach_read_from_4(buf 00443 + LOG_CHECKPOINT_CHECKSUM_1)) { 00444 return(FALSE); 00445 } 00446 00447 fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN, 00448 LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN); 00449 00450 if ((fold & 0xFFFFFFFFUL) != mach_read_from_4(buf 00451 + LOG_CHECKPOINT_CHECKSUM_2)) { 00452 return(FALSE); 00453 } 00454 00455 return(TRUE); 00456 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1899 of file log0recv.c.
References recv_parse_log_rec(), and ut_a.
Referenced by recv_parse_log_recs().
01901 : pointer to a complete log record */ 01902 ulint len) /* in: length of the log record */ 01903 { 01904 ulint i; 01905 byte type; 01906 ulint space; 01907 ulint page_no; 01908 byte* body; 01909 01910 for (i = 0; i < len; i++) { 01911 ut_a(0 == recv_parse_log_rec(ptr, ptr + i, &type, &space, 01912 &page_no, &body)); 01913 } 01914 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void recv_copy_group | ( | log_group_t * | up_to_date_group, | |
| log_group_t * | group, | |||
| dulint | recovered_lsn | |||
| ) | [static] |
Definition at line 315 of file log0recv.c.
References log_struct::buf, log_group_read_log_seg(), log_group_write_buf(), LOG_RECOVER, log_sys, OS_FILE_LOG_BLOCK_SIZE, RECV_SCAN_SIZE, log_group_struct::scanned_lsn, ut_a, ut_dulint_add(), ut_dulint_align_down(), ut_dulint_align_up(), ut_dulint_cmp(), and ut_dulint_minus().
Referenced by recv_synchronize_groups().
00317 : the most up-to-date log 00318 group */ 00319 log_group_t* group, /* in: copy to this log 00320 group */ 00321 dulint recovered_lsn) /* in: recovery succeeded up 00322 to this lsn */ 00323 { 00324 dulint start_lsn; 00325 dulint end_lsn; 00326 ulint len; 00327 00328 if (ut_dulint_cmp(group->scanned_lsn, recovered_lsn) >= 0) { 00329 00330 return; 00331 } 00332 00333 ut_a(RECV_SCAN_SIZE <= log_sys->buf_size); 00334 00335 start_lsn = ut_dulint_align_down(group->scanned_lsn, 00336 OS_FILE_LOG_BLOCK_SIZE); 00337 for (;;) { 00338 end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE); 00339 00340 if (ut_dulint_cmp(end_lsn, recovered_lsn) > 0) { 00341 end_lsn = ut_dulint_align_up(recovered_lsn, 00342 OS_FILE_LOG_BLOCK_SIZE); 00343 } 00344 00345 log_group_read_log_seg(LOG_RECOVER, log_sys->buf, 00346 up_to_date_group, start_lsn, end_lsn); 00347 00348 len = ut_dulint_minus(end_lsn, start_lsn); 00349 00350 log_group_write_buf(group, log_sys->buf, len, start_lsn, 0); 00351 00352 if (ut_dulint_cmp(end_lsn, recovered_lsn) >= 0) { 00353 00354 return; 00355 } 00356 00357 start_lsn = end_lsn; 00358 } 00359 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1050 of file log0recv.c.
References recv_struct::data, recv_struct::len, RECV_DATA_BLOCK_SIZE, and ut_memcpy().
Referenced by recv_recover_page().
01052 : buffer of length at least recv->len */ 01053 recv_t* recv) /* in: log record */ 01054 { 01055 recv_data_t* recv_data; 01056 ulint part_len; 01057 ulint len; 01058 01059 len = recv->len; 01060 recv_data = recv->data; 01061 01062 while (len > 0) { 01063 if (len > RECV_DATA_BLOCK_SIZE) { 01064 part_len = RECV_DATA_BLOCK_SIZE; 01065 } else { 01066 part_len = len; 01067 } 01068 01069 ut_memcpy(buf, ((byte*)recv_data) + sizeof(recv_data_t), 01070 part_len); 01071 buf += part_len; 01072 len -= part_len; 01073 01074 recv_data = recv_data->next; 01075 } 01076 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint recv_find_max_checkpoint | ( | log_group_t ** | max_group, | |
| ulint * | max_field | |||
| ) | [static] |
Definition at line 462 of file log0recv.c.
References buf, log_struct::checkpoint_buf, DB_ERROR, DB_SUCCESS, log_group_struct::id, LOG_CHECKPOINT_1, LOG_CHECKPOINT_2, LOG_CHECKPOINT_CHECKSUM_1, LOG_CHECKPOINT_LSN, LOG_CHECKPOINT_NO, LOG_CHECKPOINT_OFFSET, LOG_GROUP_CORRUPTED, LOG_GROUP_OK, log_group_read_checkpoint_info(), log_struct::log_groups, log_sys, log_group_struct::lsn, log_group_struct::lsn_offset, mach_read_from_4(), mach_read_from_8(), NULL, recv_check_cp_is_consistent(), log_group_struct::state, ut_dulint_cmp(), ut_dulint_get_low(), ut_dulint_zero, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by recv_recovery_from_checkpoint_start().
00464 : error code or DB_SUCCESS */ 00465 log_group_t** max_group, /* out: max group */ 00466 ulint* max_field) /* out: LOG_CHECKPOINT_1 or 00467 LOG_CHECKPOINT_2 */ 00468 { 00469 log_group_t* group; 00470 dulint max_no; 00471 dulint checkpoint_no; 00472 ulint field; 00473 byte* buf; 00474 00475 group = UT_LIST_GET_FIRST(log_sys->log_groups); 00476 00477 max_no = ut_dulint_zero; 00478 *max_group = NULL; 00479 *max_field = 0; 00480 00481 buf = log_sys->checkpoint_buf; 00482 00483 while (group) { 00484 group->state = LOG_GROUP_CORRUPTED; 00485 00486 for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; 00487 field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { 00488 00489 log_group_read_checkpoint_info(group, field); 00490 00491 if (!recv_check_cp_is_consistent(buf)) { 00492 #ifdef UNIV_DEBUG 00493 if (log_debug_writes) { 00494 fprintf(stderr, 00495 "InnoDB: Checkpoint in group %lu at %lu invalid, %lu\n", 00496 (ulong) group->id, 00497 (ulong) field, 00498 (ulong) mach_read_from_4(buf 00499 + LOG_CHECKPOINT_CHECKSUM_1)); 00500 00501 } 00502 #endif /* UNIV_DEBUG */ 00503 goto not_consistent; 00504 } 00505 00506 group->state = LOG_GROUP_OK; 00507 00508 group->lsn = mach_read_from_8(buf 00509 + LOG_CHECKPOINT_LSN); 00510 group->lsn_offset = mach_read_from_4(buf 00511 + LOG_CHECKPOINT_OFFSET); 00512 checkpoint_no = 00513 mach_read_from_8(buf + LOG_CHECKPOINT_NO); 00514 00515 #ifdef UNIV_DEBUG 00516 if (log_debug_writes) { 00517 fprintf(stderr, 00518 "InnoDB: Checkpoint number %lu found in group %lu\n", 00519 (ulong) ut_dulint_get_low(checkpoint_no), 00520 (ulong) group->id); 00521 } 00522 #endif /* UNIV_DEBUG */ 00523 00524 if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) { 00525 *max_group = group; 00526 *max_field = field; 00527 max_no = checkpoint_no; 00528 } 00529 00530 not_consistent: 00531 ; 00532 } 00533 00534 group = UT_LIST_GET_NEXT(log_groups, group); 00535 } 00536 00537 if (*max_group == NULL) { 00538 00539 fprintf(stderr, 00540 "InnoDB: No valid checkpoint found.\n" 00541 "InnoDB: If this error appears when you are creating an InnoDB database,\n" 00542 "InnoDB: the problem may be that during an earlier attempt you managed\n" 00543 "InnoDB: to create the InnoDB data files, but log file creation failed.\n" 00544 "InnoDB: If that is the case, please refer to\n" 00545 "InnoDB: http://dev.mysql.com/doc/mysql/en/Error_creating_InnoDB.html\n"); 00546 return(DB_ERROR); 00547 } 00548 00549 return(DB_SUCCESS); 00550 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 911 of file log0recv.c.
References ut_fold_ulint_pair().
Referenced by recv_add_to_hash_table(), and recv_hash().
00913 : folded value */ 00914 ulint space, /* in: space */ 00915 ulint page_no)/* in: page number */ 00916 { 00917 return(ut_fold_ulint_pair(space, page_no)); 00918 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static recv_addr_t* recv_get_fil_addr_struct | ( | ulint | space, | |
| ulint | page_no | |||
| ) | [static] |
Definition at line 938 of file log0recv.c.
References recv_sys_struct::addr_hash, HASH_GET_FIRST, HASH_GET_NEXT, recv_addr_struct::page_no, recv_hash(), recv_sys, and recv_addr_struct::space.
Referenced by recv_add_to_hash_table(), recv_read_in_area(), and recv_recover_page().
00940 : file address struct, NULL if not found from 00941 the hash table */ 00942 ulint space, /* in: space id */ 00943 ulint page_no)/* in: page number */ 00944 { 00945 recv_addr_t* recv_addr; 00946 00947 recv_addr = HASH_GET_FIRST(recv_sys->addr_hash, 00948 recv_hash(space, page_no)); 00949 while (recv_addr) { 00950 if ((recv_addr->space == space) 00951 && (recv_addr->page_no == page_no)) { 00952 00953 break; 00954 } 00955 00956 recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); 00957 } 00958 00959 return(recv_addr); 00960 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void recv_group_scan_log_recs | ( | log_group_t * | group, | |
| dulint * | contiguous_lsn, | |||
| dulint * | group_scanned_lsn | |||
| ) | [static] |
Definition at line 2526 of file log0recv.c.
References log_struct::buf, buf_pool, FALSE, yaSSL::finished, log_group_struct::id, log_group_read_log_seg(), LOG_RECOVER, log_sys, buf_pool_struct::n_frames, recv_n_pool_free_frames, recv_scan_log_recs(), RECV_SCAN_SIZE, TRUE, UNIV_PAGE_SIZE, ut_dulint_add(), ut_dulint_get_high(), and ut_dulint_get_low().
Referenced by recv_recovery_from_checkpoint_start().
02528 : log group */ 02529 dulint* contiguous_lsn, /* in/out: it is known that all log groups 02530 contain contiguous log data up to this lsn */ 02531 dulint* group_scanned_lsn)/* out: scanning succeeded up to this lsn */ 02532 { 02533 ibool finished; 02534 dulint start_lsn; 02535 dulint end_lsn; 02536 02537 finished = FALSE; 02538 02539 start_lsn = *contiguous_lsn; 02540 02541 while (!finished) { 02542 end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE); 02543 02544 log_group_read_log_seg(LOG_RECOVER, log_sys->buf, 02545 group, start_lsn, end_lsn); 02546 02547 finished = recv_scan_log_recs(TRUE, 02548 (buf_pool->n_frames 02549 - recv_n_pool_free_frames) * UNIV_PAGE_SIZE, 02550 TRUE, log_sys->buf, 02551 RECV_SCAN_SIZE, start_lsn, 02552 contiguous_lsn, group_scanned_lsn); 02553 start_lsn = end_lsn; 02554 } 02555 02556 #ifdef UNIV_DEBUG 02557 if (log_debug_writes) { 02558 fprintf(stderr, 02559 "InnoDB: Scanned group %lu up to log sequence number %lu %lu\n", 02560 (ulong) group->id, 02561 (ulong) ut_dulint_get_high(*group_scanned_lsn), 02562 (ulong) ut_dulint_get_low(*group_scanned_lsn)); 02563 } 02564 #endif /* UNIV_DEBUG */ 02565 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 925 of file log0recv.c.
References recv_sys_struct::addr_hash, hash_calc_hash(), recv_fold(), and recv_sys.
Referenced by recv_get_fil_addr_struct().
00927 : folded value */ 00928 ulint space, /* in: space */ 00929 ulint page_no)/* in: page number */ 00930 { 00931 return(hash_calc_hash(recv_fold(space, page_no), recv_sys->addr_hash)); 00932 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint recv_parse_log_rec | ( | byte * | ptr, | |
| byte * | end_ptr, | |||
| byte * | type, | |||
| ulint * | space, | |||
| ulint * | page_no, | |||
| byte ** | body | |||
| ) | [static] |
Definition at line 1802 of file log0recv.c.
References recv_sys_struct::found_corrupt_log, MLOG_DUMMY_RECORD, MLOG_MULTI_REC_END, mlog_parse_initial_log_record(), NULL, recv_max_parsed_page_no, recv_parse_or_apply_log_rec_body(), recv_sys, and TRUE.
Referenced by recv_check_incomplete_log_recs(), and recv_parse_log_recs().
01804 : length of the record, or 0 if the record was 01805 not complete */ 01806 byte* ptr, /* in: pointer to a buffer */ 01807 byte* end_ptr,/* in: pointer to the buffer end */ 01808 byte* type, /* out: type */ 01809 ulint* space, /* out: space id */ 01810 ulint* page_no,/* out: page number */ 01811 byte** body) /* out: log record body start */ 01812 { 01813 byte* new_ptr; 01814 01815 *body = NULL; 01816 01817 if (ptr == end_ptr) { 01818 01819 return(0); 01820 } 01821 01822 if (*ptr == MLOG_MULTI_REC_END) { 01823 01824 *type = *ptr; 01825 01826 return(1); 01827 } 01828 01829 if (*ptr == MLOG_DUMMY_RECORD) { 01830 *type = *ptr; 01831 01832 *space = ULINT_UNDEFINED - 1; /* For debugging */ 01833 01834 return(1); 01835 } 01836 01837 new_ptr = mlog_parse_initial_log_record(ptr, end_ptr, type, space, 01838 page_no); 01839 *body = new_ptr; 01840 01841 if (UNIV_UNLIKELY(!new_ptr)) { 01842 01843 return(0); 01844 } 01845 01846 /* Check that page_no is sensible */ 01847 01848 if (UNIV_UNLIKELY(*page_no > 0x8FFFFFFFUL)) { 01849 01850 recv_sys->found_corrupt_log = TRUE; 01851 01852 return(0); 01853 } 01854 01855 new_ptr = recv_parse_or_apply_log_rec_body(*type, new_ptr, end_ptr, 01856 NULL, NULL); 01857 if (UNIV_UNLIKELY(new_ptr == NULL)) { 01858 01859 return(0); 01860 } 01861 01862 if (*page_no > recv_max_parsed_page_no) { 01863 recv_max_parsed_page_no = *page_no; 01864 } 01865 01866 return(new_ptr - ptr); 01867 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool recv_parse_log_recs | ( | ibool | store_to_hash | ) | [static] |
Definition at line 1976 of file log0recv.c.
References recv_sys_struct::buf, FALSE, fil_op_log_parse_or_replay(), recv_sys_struct::found_corrupt_log, recv_sys_struct::len, log_sys, MLOG_DUMMY_RECORD, MLOG_FILE_CREATE, MLOG_FILE_DELETE, MLOG_FILE_RENAME, MLOG_MULTI_REC_END, MLOG_SINGLE_REC_FLAG, log_struct::mutex, NULL, recv_sys_struct::parse_start_lsn, recv_sys_struct::recovered_lsn, recv_sys_struct::recovered_offset, recv_add_to_hash_table(), recv_calc_lsn_on_data_add(), recv_check_incomplete_log_recs(), recv_parse_log_rec(), recv_previous_parsed_rec_is_multi, recv_previous_parsed_rec_offset, recv_previous_parsed_rec_type, recv_report_corrupt_log(), recv_sys, recv_sys_struct::scanned_lsn, TRUE, ut_a, ut_ad, ut_dulint_cmp(), and ut_dulint_is_zero().
Referenced by recv_scan_log_recs().
01978 : currently always returns FALSE */ 01979 ibool store_to_hash) /* in: TRUE if the records should be stored 01980 to the hash table; this is set to FALSE if just 01981 debug checking is needed */ 01982 { 01983 byte* ptr; 01984 byte* end_ptr; 01985 ulint single_rec; 01986 ulint len; 01987 ulint total_len; 01988 dulint new_recovered_lsn; 01989 dulint old_lsn; 01990 byte type; 01991 ulint space; 01992 ulint page_no; 01993 byte* body; 01994 ulint n_recs; 01995 01996 #ifdef UNIV_SYNC_DEBUG 01997 ut_ad(mutex_own(&(log_sys->mutex))); 01998 #endif /* UNIV_SYNC_DEBUG */ 01999 ut_ad(!ut_dulint_is_zero(recv_sys->parse_start_lsn)); 02000 loop: 02001 ptr = recv_sys->buf + recv_sys->recovered_offset; 02002 02003 end_ptr = recv_sys->buf + recv_sys->len; 02004 02005 if (ptr == end_ptr) { 02006 02007 return(FALSE); 02008 } 02009 02010 single_rec = (ulint)*ptr & MLOG_SINGLE_REC_FLAG; 02011 02012 if (single_rec || *ptr == MLOG_DUMMY_RECORD) { 02013 /* The mtr only modified a single page, or this is a file op */ 02014 02015 old_lsn = recv_sys->recovered_lsn; 02016 02017 /* Try to parse a log record, fetching its type, space id, 02018 page no, and a pointer to the body of the log record */ 02019 02020 len = recv_parse_log_rec(ptr, end_ptr, &type, &space, 02021 &page_no, &body); 02022 02023 if (len == 0 || recv_sys->found_corrupt_log) { 02024 if (recv_sys->found_corrupt_log) { 02025 02026 recv_report_corrupt_log(ptr, 02027 type, space, page_no); 02028 } 02029 02030 return(FALSE); 02031 } 02032 02033 new_recovered_lsn = recv_calc_lsn_on_data_add(old_lsn, len); 02034 02035 if (ut_dulint_cmp(new_recovered_lsn, recv_sys->scanned_lsn) 02036 > 0) { 02037 /* The log record filled a log block, and we require 02038 that also the next log block should have been scanned 02039 in */ 02040 02041 return(FALSE); 02042 } 02043 02044 recv_previous_parsed_rec_type = (ulint)type; 02045 recv_previous_parsed_rec_offset = recv_sys->recovered_offset; 02046 recv_previous_parsed_rec_is_multi = 0; 02047 02048 recv_sys->recovered_offset += len; 02049 recv_sys->recovered_lsn = new_recovered_lsn; 02050 02051 #ifdef UNIV_DEBUG 02052 if (log_debug_writes) { 02053 fprintf(stderr, 02054 "InnoDB: Parsed a single log rec type %lu len %lu space %lu page no %lu\n", 02055 (ulong) type, (ulong) len, (ulong) space, 02056 (ulong) page_no); 02057 } 02058 #endif /* UNIV_DEBUG */ 02059 02060 if (type == MLOG_DUMMY_RECORD) { 02061 /* Do nothing */ 02062 02063 } else if (store_to_hash && (type == MLOG_FILE_CREATE 02064 || type == MLOG_FILE_RENAME 02065 || type == MLOG_FILE_DELETE)) { 02066 #ifdef UNIV_HOTBACKUP 02067 if (recv_replay_file_ops) { 02068 02069 /* In ibbackup --apply-log, replay an .ibd file 02070 operation, if possible; note that 02071 fil_path_to_mysql_datadir is set in ibbackup to 02072 point to the datadir we should use there */ 02073 02074 if (NULL == fil_op_log_parse_or_replay(body, 02075 end_ptr, type, TRUE, space)) { 02076 fprintf(stderr, 02077 "InnoDB: Error: file op log record of type %lu space %lu not complete in\n" 02078 "InnoDB: the replay phase. Path %s\n", (ulint)type, space, (char*)(body + 2)); 02079 02080 ut_a(0); 02081 } 02082 } 02083 #endif 02084 /* In normal mysqld crash recovery we do not try to 02085 replay file operations */ 02086 } else if (store_to_hash) { 02087 recv_add_to_hash_table(type, space, page_no, body, 02088 ptr + len, old_lsn, 02089 recv_sys->recovered_lsn); 02090 } else { 02091 /* In debug checking, update a replicate page 02092 according to the log record, and check that it 02093 becomes identical with the original page */ 02094 #ifdef UNIV_LOG_DEBUG 02095 recv_check_incomplete_log_recs(ptr, len); 02096 #endif/* UNIV_LOG_DEBUG */ 02097 #ifdef UNIV_LOG_REPLICATE 02098 recv_update_replicate(type, space, page_no, body, 02099 ptr + len); 02100 recv_compare_replicate(space, page_no); 02101 #endif /* UNIV_LOG_REPLICATE */ 02102 02103 } 02104 } else { 02105 /* Check that all the records associated with the single mtr 02106 are included within the buffer */ 02107 02108 total_len = 0; 02109 n_recs = 0; 02110 02111 for (;;) { 02112 len = recv_parse_log_rec(ptr, end_ptr, &type, &space, 02113 &page_no, &body); 02114 if (len == 0 || recv_sys->found_corrupt_log) { 02115 02116 if (recv_sys->found_corrupt_log) { 02117 02118 recv_report_corrupt_log(ptr, 02119 type, space, page_no); 02120 } 02121 02122 return(FALSE); 02123 } 02124 02125 recv_previous_parsed_rec_type = (ulint)type; 02126 recv_previous_parsed_rec_offset 02127 = recv_sys->recovered_offset + total_len; 02128 recv_previous_parsed_rec_is_multi = 1; 02129 02130 if ((!store_to_hash) && (type != MLOG_MULTI_REC_END)) { 02131 /* In debug checking, update a replicate page 02132 according to the log record */ 02133 #ifdef UNIV_LOG_DEBUG 02134 recv_check_incomplete_log_recs(ptr, len); 02135 #endif /* UNIV_LOG_DEBUG */ 02136 #ifdef UNIV_LOG_REPLICATE 02137 recv_update_replicate(type, space, page_no, 02138 body, ptr + len); 02139 #endif /* UNIV_LOG_REPLICATE */ 02140 } 02141 02142 #ifdef UNIV_DEBUG 02143 if (log_debug_writes) { 02144 fprintf(stderr, 02145 "InnoDB: Parsed a multi log rec type %lu len %lu space %lu page no %lu\n", 02146 (ulong) type, (ulong) len, (ulong) space, 02147 (ulong) page_no); 02148 } 02149 #endif /* UNIV_DEBUG */ 02150 02151 total_len += len; 02152 n_recs++; 02153 02154 ptr += len; 02155 02156 if (type == MLOG_MULTI_REC_END) { 02157 02158 /* Found the end mark for the records */ 02159 02160 break; 02161 } 02162 } 02163 02164 new_recovered_lsn = recv_calc_lsn_on_data_add( 02165 recv_sys->recovered_lsn, total_len); 02166 02167 if (ut_dulint_cmp(new_recovered_lsn, recv_sys->scanned_lsn) 02168 > 0) { 02169 /* The log record filled a log block, and we require 02170 that also the next log block should have been scanned 02171 in */ 02172 02173 return(FALSE); 02174 } 02175 02176 /* Add all the records to the hash table */ 02177 02178 ptr = recv_sys->buf + recv_sys->recovered_offset; 02179 02180 for (;;) { 02181 old_lsn = recv_sys->recovered_lsn; 02182 len = recv_parse_log_rec(ptr, end_ptr, &type, &space, 02183 &page_no, &body); 02184 if (recv_sys->found_corrupt_log) { 02185 02186 recv_report_corrupt_log(ptr, 02187 type, space, page_no); 02188 } 02189 02190 ut_a(len != 0); 02191 ut_a(0 == ((ulint)*ptr & MLOG_SINGLE_REC_FLAG)); 02192 02193 recv_sys->recovered_offset += len; 02194 recv_sys->recovered_lsn = recv_calc_lsn_on_data_add( 02195 old_lsn, len); 02196 if (type == MLOG_MULTI_REC_END) { 02197 02198 /* Found the end mark for the records */ 02199 02200 break; 02201 } 02202 02203 if (store_to_hash) { 02204 recv_add_to_hash_table(type, space, page_no, 02205 body, ptr + len, old_lsn, 02206 new_recovered_lsn); 02207 #ifdef UNIV_LOG_REPLICATE 02208 } else { 02209 /* In debug checking, check that the replicate 02210 page has become identical with the original 02211 page */ 02212 recv_compare_replicate(space, page_no); 02213 #endif /* UNIV_LOG_REPLICATE */ 02214 } 02215 02216 ptr += len; 02217 } 02218 } 02219 02220 goto loop; 02221 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static byte* recv_parse_or_apply_log_rec_body | ( | byte | type, | |
| byte * | ptr, | |||
| byte * | end_ptr, | |||
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 748 of file log0recv.c.
References btr_cur_parse_del_mark_set_clust_rec(), btr_cur_parse_del_mark_set_sec_rec(), btr_cur_parse_update_in_place(), btr_parse_page_reorganize(), btr_parse_set_min_rec_mark(), dict_mem_index_free(), dict_mem_table_free(), dict_table_is_comp(), FALSE, fil_op_log_parse_or_replay(), recv_sys_struct::found_corrupt_log, fsp_parse_init_file_page(), ibuf_parse_bitmap_init(), index(), MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES, MLOG_8BYTES, MLOG_COMP_LIST_END_COPY_CREATED, MLOG_COMP_LIST_END_DELETE, MLOG_COMP_LIST_START_DELETE, MLOG_COMP_PAGE_CREATE, MLOG_COMP_PAGE_REORGANIZE, MLOG_COMP_REC_CLUST_DELETE_MARK, MLOG_COMP_REC_DELETE, MLOG_COMP_REC_INSERT, MLOG_COMP_REC_MIN_MARK, MLOG_COMP_REC_SEC_DELETE_MARK, MLOG_COMP_REC_UPDATE_IN_PLACE, MLOG_FILE_CREATE, MLOG_FILE_DELETE, MLOG_FILE_RENAME, MLOG_IBUF_BITMAP_INIT, MLOG_INIT_FILE_PAGE, MLOG_LIST_END_COPY_CREATED, MLOG_LIST_END_DELETE, MLOG_LIST_START_DELETE, MLOG_PAGE_CREATE, MLOG_PAGE_REORGANIZE, mlog_parse_index(), mlog_parse_nbytes(), mlog_parse_string(), MLOG_REC_CLUST_DELETE_MARK, MLOG_REC_DELETE, MLOG_REC_INSERT, MLOG_REC_MIN_MARK, MLOG_REC_SEC_DELETE_MARK, MLOG_REC_UPDATE_IN_PLACE, MLOG_UNDO_ERASE_END, MLOG_UNDO_HDR_CREATE, MLOG_UNDO_HDR_DISCARD, MLOG_UNDO_HDR_REUSE, MLOG_UNDO_INIT, MLOG_UNDO_INSERT, MLOG_WRITE_STRING, NULL, page_cur_parse_delete_rec(), page_cur_parse_insert_rec(), page_is_comp(), page_parse_copy_rec_list_to_created_page(), page_parse_create(), page_parse_delete_rec_list(), recv_sys, TRUE, trx_undo_parse_add_undo_rec(), trx_undo_parse_discard_latest(), trx_undo_parse_erase_page_end(), trx_undo_parse_page_header(), trx_undo_parse_page_init(), and ut_a.
Referenced by recv_parse_log_rec(), and recv_recover_page().
00750 : log record end, NULL if not a complete 00751 record */ 00752 byte type, /* in: type */ 00753 byte* ptr, /* in: pointer to a buffer */ 00754 byte* end_ptr,/* in: pointer to the buffer end */ 00755 page_t* page, /* in: buffer page or NULL; if not NULL, then the log 00756 record is applied to the page, and the log record 00757 should be complete then */ 00758 mtr_t* mtr) /* in: mtr or NULL; should be non-NULL if and only if 00759 page is non-NULL */ 00760 { 00761 dict_index_t* index = NULL; 00762 00763 switch (type) { 00764 case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES: 00765 ptr = mlog_parse_nbytes(type, ptr, end_ptr, page); 00766 break; 00767 case MLOG_REC_INSERT: case MLOG_COMP_REC_INSERT: 00768 if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, 00769 type == MLOG_COMP_REC_INSERT, &index))) { 00770 ut_a(!page 00771 || (ibool)!!page_is_comp(page) 00772 == dict_table_is_comp(index->table)); 00773 ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr, 00774 index, page, mtr); 00775 } 00776 break; 00777 case MLOG_REC_CLUST_DELETE_MARK: case MLOG_COMP_REC_CLUST_DELETE_MARK: 00778 if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, 00779 type == MLOG_COMP_REC_CLUST_DELETE_MARK, &index))) { 00780 ut_a(!page 00781 || (ibool)!!page_is_comp(page) 00782 == dict_table_is_comp(index->table)); 00783 ptr = btr_cur_parse_del_mark_set_clust_rec(ptr, 00784 end_ptr, index, page); 00785 } 00786 break; 00787 case MLOG_COMP_REC_SEC_DELETE_MARK: 00788 /* This log record type is obsolete, but we process it for 00789 backward compatibility with MySQL 5.0.3 and 5.0.4. */ 00790 ut_a(!page || page_is_comp(page)); 00791 ptr = mlog_parse_index(ptr, end_ptr, TRUE, &index); 00792 if (!ptr) { 00793 break; 00794 } 00795 /* Fall through */ 00796 case MLOG_REC_SEC_DELETE_MARK: 00797 ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr, page); 00798 break; 00799 case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE: 00800 if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, 00801 type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) { 00802 ut_a(!page 00803 || (ibool)!!page_is_comp(page) 00804 == dict_table_is_comp(index->table)); 00805 ptr = btr_cur_parse_update_in_place(ptr, end_ptr, 00806 page, index); 00807 } 00808 break; 00809 case MLOG_LIST_END_DELETE: case MLOG_COMP_LIST_END_DELETE: 00810 case MLOG_LIST_START_DELETE: case MLOG_COMP_LIST_START_DELETE: 00811 if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, 00812 type == MLOG_COMP_LIST_END_DELETE 00813 || type == MLOG_COMP_LIST_START_DELETE, &index))) { 00814 ut_a(!page 00815 || (ibool)!!page_is_comp(page) 00816 == dict_table_is_comp(index->table)); 00817 ptr = page_parse_delete_rec_list(type, ptr, end_ptr, 00818 index, page, mtr); 00819 } 00820 break; 00821 case MLOG_LIST_END_COPY_CREATED: case MLOG_COMP_LIST_END_COPY_CREATED: 00822 if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, 00823 type == MLOG_COMP_LIST_END_COPY_CREATED, &index))) { 00824 ut_a(!page 00825 || (ibool)!!page_is_comp(page) 00826 == dict_table_is_comp(index->table)); 00827 ptr = page_parse_copy_rec_list_to_created_page(ptr, 00828 end_ptr, index, page, mtr); 00829 } 00830 break; 00831 case MLOG_PAGE_REORGANIZE: case MLOG_COMP_PAGE_REORGANIZE: 00832 if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, 00833 type == MLOG_COMP_PAGE_REORGANIZE, &index))) { 00834 ut_a(!page 00835 || (ibool)!!page_is_comp(page) 00836 == dict_table_is_comp(index->table)); 00837 ptr = btr_parse_page_reorganize(ptr, end_ptr, index, 00838 page, mtr); 00839 } 00840 break; 00841 case MLOG_PAGE_CREATE: case MLOG_COMP_PAGE_CREATE: 00842 ptr = page_parse_create(ptr, end_ptr, 00843 type == MLOG_COMP_PAGE_CREATE, page, mtr); 00844 break; 00845 case MLOG_UNDO_INSERT: 00846 ptr = trx_undo_parse_add_undo_rec(ptr, end_ptr, page); 00847 break; 00848 case MLOG_UNDO_ERASE_END: 00849 ptr = trx_undo_parse_erase_page_end(ptr, end_ptr, page, mtr); 00850 break; 00851 case MLOG_UNDO_INIT: 00852 ptr = trx_undo_parse_page_init(ptr, end_ptr, page, mtr); 00853 break; 00854 case MLOG_UNDO_HDR_DISCARD: 00855 ptr = trx_undo_parse_discard_latest(ptr, end_ptr, page, mtr); 00856 break; 00857 case MLOG_UNDO_HDR_CREATE: 00858 case MLOG_UNDO_HDR_REUSE: 00859 ptr = trx_undo_parse_page_header(type, ptr, end_ptr, 00860 page, mtr); 00861 break; 00862 case MLOG_REC_MIN_MARK: case MLOG_COMP_REC_MIN_MARK: 00863 ptr = btr_parse_set_min_rec_mark(ptr, end_ptr, 00864 type == MLOG_COMP_REC_MIN_MARK, page, mtr); 00865 break; 00866 case MLOG_REC_DELETE: case MLOG_COMP_REC_DELETE: 00867 if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, 00868 type == MLOG_COMP_REC_DELETE, &index))) { 00869 ut_a(!page 00870 || (ibool)!!page_is_comp(page) 00871 == dict_table_is_comp(index->table)); 00872 ptr = page_cur_parse_delete_rec(ptr, end_ptr, 00873 index, page, mtr); 00874 } 00875 break; 00876 case MLOG_IBUF_BITMAP_INIT: 00877 ptr = ibuf_parse_bitmap_init(ptr, end_ptr, page, mtr); 00878 break; 00879 case MLOG_INIT_FILE_PAGE: 00880 ptr = fsp_parse_init_file_page(ptr, end_ptr, page); 00881 break; 00882 case MLOG_WRITE_STRING: 00883 ptr = mlog_parse_string(ptr, end_ptr, page); 00884 break; 00885 case MLOG_FILE_CREATE: 00886 case MLOG_FILE_RENAME: 00887 case MLOG_FILE_DELETE: 00888 ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE, 00889 ULINT_UNDEFINED); 00890 break; 00891 default: 00892 ptr = NULL; 00893 recv_sys->found_corrupt_log = TRUE; 00894 } 00895 00896 if (index) { 00897 dict_table_t* table = index->table; 00898 00899 dict_mem_index_free(index); 00900 dict_mem_table_free(table); 00901 } 00902 00903 return(ptr); 00904 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool recv_read_cp_info_for_backup | ( | byte * | hdr, | |
| dulint * | lsn, | |||
| ulint * | offset, | |||
| ulint * | fsp_limit, | |||
| dulint * | cp_no, | |||
| dulint * | first_header_lsn | |||
| ) |
Definition at line 556 of file log0recv.c.
References FALSE, LOG_CHECKPOINT_1, LOG_CHECKPOINT_2, LOG_CHECKPOINT_FSP_FREE_LIMIT, LOG_CHECKPOINT_FSP_MAGIC_N, LOG_CHECKPOINT_FSP_MAGIC_N_VAL, LOG_CHECKPOINT_LSN, LOG_CHECKPOINT_NO, LOG_CHECKPOINT_OFFSET, LOG_FILE_START_LSN, mach_read_from_4(), mach_read_from_8(), recv_check_cp_is_consistent(), TRUE, ut_dulint_cmp(), and ut_dulint_zero.
00558 : TRUE if success */ 00559 byte* hdr, /* in: buffer containing the log group header */ 00560 dulint* lsn, /* out: checkpoint lsn */ 00561 ulint* offset, /* out: checkpoint offset in the log group */ 00562 ulint* fsp_limit,/* out: fsp limit of space 0, 1000000000 if the 00563 database is running with < version 3.23.50 of InnoDB */ 00564 dulint* cp_no, /* out: checkpoint number */ 00565 dulint* first_header_lsn) 00566 /* out: lsn of of the start of the first log file */ 00567 { 00568 ulint max_cp = 0; 00569 dulint max_cp_no = ut_dulint_zero; 00570 byte* cp_buf; 00571 00572 cp_buf = hdr + LOG_CHECKPOINT_1; 00573 00574 if (recv_check_cp_is_consistent(cp_buf)) { 00575 max_cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO); 00576 max_cp = LOG_CHECKPOINT_1; 00577 } 00578 00579 cp_buf = hdr + LOG_CHECKPOINT_2; 00580 00581 if (recv_check_cp_is_consistent(cp_buf)) { 00582 if (ut_dulint_cmp(mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO), 00583 max_cp_no) > 0) { 00584 max_cp = LOG_CHECKPOINT_2; 00585 } 00586 } 00587 00588 if (max_cp == 0) { 00589 return(FALSE); 00590 } 00591 00592 cp_buf = hdr + max_cp; 00593 00594 *lsn = mach_read_from_8(cp_buf + LOG_CHECKPOINT_LSN); 00595 *offset = mach_read_from_4(cp_buf + LOG_CHECKPOINT_OFFSET); 00596 00597 /* If the user is running a pre-3.23.50 version of InnoDB, its 00598 checkpoint data does not contain the fsp limit info */ 00599 if (mach_read_from_4(cp_buf + LOG_CHECKPOINT_FSP_MAGIC_N) 00600 == LOG_CHECKPOINT_FSP_MAGIC_N_VAL) { 00601 00602 *fsp_limit = mach_read_from_4( 00603 cp_buf + LOG_CHECKPOINT_FSP_FREE_LIMIT); 00604 00605 if (*fsp_limit == 0) { 00606 *fsp_limit = 1000000000; 00607 } 00608 } else { 00609 *fsp_limit = 1000000000; 00610 } 00611 00612 /* fprintf(stderr, "fsp limit %lu MB\n", *fsp_limit); */ 00613 00614 *cp_no = mach_read_from_8(cp_buf + LOG_CHECKPOINT_NO); 00615 00616 *first_header_lsn = mach_read_from_8(hdr + LOG_FILE_START_LSN); 00617 00618 return(TRUE); 00619 }
Here is the call graph for this function:

Definition at line 1277 of file log0recv.c.
References buf_page_peek(), recv_sys_struct::mutex, mutex_enter, mutex_exit(), n, RECV_BEING_READ, recv_get_fil_addr_struct(), RECV_NOT_PROCESSED, RECV_READ_AHEAD_AREA, recv_sys, and recv_addr_struct::state.
Referenced by recv_apply_hashed_log_recs().
01279 : number of pages found */ 01280 ulint space, /* in: space */ 01281 ulint page_no)/* in: page number */ 01282 { 01283 recv_addr_t* recv_addr; 01284 ulint page_nos[RECV_READ_AHEAD_AREA]; 01285 ulint low_limit; 01286 ulint n; 01287 01288 low_limit = page_no - (page_no % RECV_READ_AHEAD_AREA); 01289 01290 n = 0; 01291 01292 for (page_no = low_limit; page_no < low_limit + RECV_READ_AHEAD_AREA; 01293 page_no++) { 01294 recv_addr = recv_get_fil_addr_struct(space, page_no); 01295 01296 if (recv_addr && !buf_page_peek(space, page_no)) { 01297 01298 mutex_enter(&(recv_sys->mutex)); 01299 01300 if (recv_addr->state == RECV_NOT_PROCESSED) { 01301 recv_addr->state = RECV_BEING_READ; 01302 01303 page_nos[n] = page_no; 01304 01305 n++; 01306 } 01307 01308 mutex_exit(&(recv_sys->mutex)); 01309 } 01310 } 01311 01312 buf_read_recv_pages(FALSE, space, page_nos, n); 01313 /* 01314 fprintf(stderr, "Recv pages at %lu n %lu\n", page_nos[0], n); 01315 */ 01316 return(n); 01317 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void recv_recover_page | ( | ibool | recover_backup, | |
| ibool | just_read_in, | |||
| page_t * | page, | |||
| ulint | space, | |||
| ulint | page_no | |||
| ) |
Definition at line 1084 of file log0recv.c.
References recv_sys_struct::apply_log_recs, yaSSL::block, buf, buf_block_align(), buf_flush_recv_note_modification(), buf_frame_get_newest_modification(), BUF_KEEP_OLD, buf_page_get_known_nowait(), recv_struct::data, recv_struct::end_lsn, FALSE, FIL_PAGE_END_LSN_OLD_CHKSUM, FIL_PAGE_LSN, recv_struct::len, mach_read_from_8(), mach_write_to_8(), mem_alloc, mem_free, MLOG_INIT_FILE_PAGE, mtr_struct::modifications, mtr_commit(), MTR_LOG_NONE, mtr_set_log_mode(), mtr_start(), recv_sys_struct::mutex, mutex_enter, mutex_exit(), recv_sys_struct::n_addrs, NULL, recv_addr_struct::page_no, recv_addr_struct::rec_list, RECV_BEING_PROCESSED, RECV_DATA_BLOCK_SIZE, recv_data_copy_to_buf(), recv_get_fil_addr_struct(), recv_max_page_lsn, recv_parse_or_apply_log_rec_body(), RECV_PROCESSED, recv_sys, rw_lock_x_lock_move_ownership(), RW_X_LATCH, recv_addr_struct::space, recv_struct::start_lsn, recv_addr_struct::state, SYNC_NO_ORDER_CHECK, TRUE, recv_struct::type, UNIV_PAGE_SIZE, ut_a, ut_dulint_add(), ut_dulint_cmp(), ut_dulint_is_zero(), ut_dulint_zero, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by buf_page_io_complete(), recv_apply_hashed_log_recs(), and recv_apply_log_recs_for_backup().
01086 : TRUE if we are recovering a backup 01087 page: then we do not acquire any latches 01088 since the page was read in outside the 01089 buffer pool */ 01090 ibool just_read_in, /* in: TRUE if the i/o-handler calls this for 01091 a freshly read page */ 01092 page_t* page, /* in: buffer page */ 01093 ulint space, /* in: space id */ 01094 ulint page_no) /* in: page number */ 01095 { 01096 buf_block_t* block = NULL; 01097 recv_addr_t* recv_addr; 01098 recv_t* recv; 01099 byte* buf; 01100 dulint start_lsn; 01101 dulint end_lsn; 01102 dulint page_lsn; 01103 dulint page_newest_lsn; 01104 ibool modification_to_page; 01105 ibool success; 01106 mtr_t mtr; 01107 01108 mutex_enter(&(recv_sys->mutex)); 01109 01110 if (recv_sys->apply_log_recs == FALSE) { 01111 01112 /* Log records should not be applied now */ 01113 01114 mutex_exit(&(recv_sys->mutex)); 01115 01116 return; 01117 } 01118 01119 recv_addr = recv_get_fil_addr_struct(space, page_no); 01120 01121 if ((recv_addr == NULL) 01122 || (recv_addr->state == RECV_BEING_PROCESSED) 01123 || (recv_addr->state == RECV_PROCESSED)) { 01124 01125 mutex_exit(&(recv_sys->mutex)); 01126 01127 return; 01128 } 01129 01130 /* fprintf(stderr, "Recovering space %lu, page %lu\n", space, page_no); */ 01131 01132 recv_addr->state = RECV_BEING_PROCESSED; 01133 01134 mutex_exit(&(recv_sys->mutex)); 01135 01136 mtr_start(&mtr); 01137 mtr_set_log_mode(&mtr, MTR_LOG_NONE); 01138 01139 if (!recover_backup) { 01140 block = buf_block_align(page); 01141 01142 if (just_read_in) { 01143 /* Move the ownership of the x-latch on the page to this OS 01144 thread, so that we can acquire a second x-latch on it. This 01145 is needed for the operations to the page to pass the debug 01146 checks. */ 01147 01148 rw_lock_x_lock_move_ownership(&(block->lock)); 01149 } 01150 01151 success = buf_page_get_known_nowait(RW_X_LATCH, page, 01152 BUF_KEEP_OLD, 01153 __FILE__, __LINE__, 01154 &mtr); 01155 ut_a(success); 01156 01157 #ifdef UNIV_SYNC_DEBUG 01158 buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK); 01159 #endif /* UNIV_SYNC_DEBUG */ 01160 } 01161 01162 /* Read the newest modification lsn from the page */ 01163 page_lsn = mach_read_from_8(page + FIL_PAGE_LSN); 01164 01165 if (!recover_backup) { 01166 /* It may be that the page has been modified in the buffer 01167 pool: read the newest modification lsn there */ 01168 01169 page_newest_lsn = buf_frame_get_newest_modification(page); 01170 01171 if (!ut_dulint_is_zero(page_newest_lsn)) { 01172 01173 page_lsn = page_newest_lsn; 01174 } 01175 } else { 01176 /* In recovery from a backup we do not really use the buffer 01177 pool */ 01178 01179 page_newest_lsn = ut_dulint_zero; 01180 } 01181 01182 modification_to_page = FALSE; 01183 start_lsn = end_lsn = ut_dulint_zero; 01184 01185 recv = UT_LIST_GET_FIRST(recv_addr->rec_list); 01186 01187 while (recv) { 01188 end_lsn = recv->end_lsn; 01189 01190 if (recv->len > RECV_DATA_BLOCK_SIZE) { 01191 /* We have to copy the record body to a separate 01192 buffer */ 01193 01194 buf = mem_alloc(recv->len); 01195 01196 recv_data_copy_to_buf(buf, recv); 01197 } else { 01198 buf = ((byte*)(recv->data)) + sizeof(recv_data_t); 01199 } 01200 01201 if (recv->type == MLOG_INIT_FILE_PAGE) { 01202 page_lsn = page_newest_lsn; 01203 01204 mach_write_to_8(page + UNIV_PAGE_SIZE 01205 - FIL_PAGE_END_LSN_OLD_CHKSUM, ut_dulint_zero); 01206 mach_write_to_8(page + FIL_PAGE_LSN, ut_dulint_zero); 01207 } 01208 01209 if (ut_dulint_cmp(recv->start_lsn, page_lsn) >= 0) { 01210 01211 if (!modification_to_page) { 01212 01213 modification_to_page = TRUE; 01214 start_lsn = recv->start_lsn; 01215 } 01216 01217 #ifdef UNIV_DEBUG 01218 if (log_debug_writes) { 01219 fprintf(stderr, 01220 "InnoDB: Applying log rec type %lu len %lu to space %lu page no %lu\n", 01221 (ulong) recv->type, (ulong) recv->len, 01222 (ulong) recv_addr->space, 01223 (ulong) recv_addr->page_no); 01224 } 01225 #endif /* UNIV_DEBUG */ 01226 01227 recv_parse_or_apply_log_rec_body(recv->type, buf, 01228 buf + recv->len, page, &mtr); 01229 mach_write_to_8(page + UNIV_PAGE_SIZE 01230 - FIL_PAGE_END_LSN_OLD_CHKSUM, 01231 ut_dulint_add(recv->start_lsn, 01232 recv->len)); 01233 mach_write_to_8(page + FIL_PAGE_LSN, 01234 ut_dulint_add(recv->start_lsn, 01235 recv->len)); 01236 } 01237 01238 if (recv->len > RECV_DATA_BLOCK_SIZE) { 01239 mem_free(buf); 01240 } 01241 01242 recv = UT_LIST_GET_NEXT(rec_list, recv); 01243 } 01244 01245 mutex_enter(&(recv_sys->mutex)); 01246 01247 if (ut_dulint_cmp(recv_max_page_lsn, page_lsn) < 0) { 01248 recv_max_page_lsn = page_lsn; 01249 } 01250 01251 recv_addr->state = RECV_PROCESSED; 01252 01253 ut_a(recv_sys->n_addrs); 01254 recv_sys->n_addrs--; 01255 01256 mutex_exit(&(recv_sys->mutex)); 01257 01258 if (!recover_backup && modification_to_page) { 01259 ut_a(block); 01260 01261 buf_flush_recv_note_modification(block, start_lsn, end_lsn); 01262 } 01263 01264 /* Make sure that committing mtr does not change the modification 01265 lsn values of page */ 01266 01267 mtr.modifications = FALSE; 01268 01269 mtr_commit(&mtr); 01270 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void recv_recovery_from_checkpoint_finish | ( | void | ) |
Definition at line 2937 of file log0recv.c.
References FALSE, recv_sys_struct::found_corrupt_log, NULL, os_thread_create(), recv_apply_hashed_log_recs(), recv_needed_recovery, recv_recovery_on, recv_sys, recv_sys_free(), SRV_FORCE_NO_LOG_REDO, SRV_FORCE_NO_TRX_UNDO, srv_force_recovery, TRUE, trx_rollback_or_clean_all_without_sess(), trx_sys_print_mysql_binlog_offset(), and trx_sys_print_mysql_master_log_pos().
Referenced by innobase_start_or_create_for_mysql().
02939 { 02940 int i; 02941 02942 /* Apply the hashed log records to the respective file pages */ 02943 02944 if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { 02945 02946 recv_apply_hashed_log_recs(TRUE); 02947 } 02948 02949 #ifdef UNIV_DEBUG 02950 if (log_debug_writes) { 02951 fprintf(stderr, 02952 "InnoDB: Log records applied to the database\n"); 02953 } 02954 #endif /* UNIV_DEBUG */ 02955 02956 if (recv_needed_recovery) { 02957 trx_sys_print_mysql_master_log_pos(); 02958 trx_sys_print_mysql_binlog_offset(); 02959 } 02960 02961 if (recv_sys->found_corrupt_log) { 02962 02963 fprintf(stderr, 02964 "InnoDB: WARNING: the log file may have been corrupt and it\n" 02965 "InnoDB: is possible that the log scan or parsing did not proceed\n" 02966 "InnoDB: far enough in recovery. Please run CHECK TABLE\n" 02967 "InnoDB: on your InnoDB tables to check that they are ok!\n" 02968 "InnoDB: It may be safest to recover your InnoDB database from\n" 02969 "InnoDB: a backup!\n"); 02970 } 02971 02972 /* Free the resources of the recovery system */ 02973 02974 recv_recovery_on = FALSE; 02975 02976 #ifndef UNIV_LOG_DEBUG 02977 recv_sys_free(); 02978 #endif 02979 if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) { 02980 /* Rollback the uncommitted transactions which have no user 02981 session */ 02982 02983 os_thread_create(trx_rollback_or_clean_all_without_sess, 02984 (void *)&i, NULL); 02985 } 02986 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint recv_recovery_from_checkpoint_start | ( | ulint | type, | |
| dulint | limit_lsn, | |||
| dulint | min_flushed_lsn, | |||
| dulint | max_flushed_lsn | |||
| ) |
Definition at line 2574 of file log0recv.c.
References recv_sys_struct::apply_log_recs, recv_sys_struct::archive_group, log_group_struct::archived_file_no, log_struct::archived_lsn, log_group_struct::archived_offset, log_struct::archiving_state, log_struct::buf, buf, log_struct::buf_free, log_struct::buf_next_to_write, buf_pool_get_curr_size(), log_struct::checkpoint_buf, DB_ERROR, DB_SUCCESS, err, FALSE, fil_io(), fil_load_single_table_tablespaces(), log_group_struct::id, recv_sys_struct::last_block, log_struct::last_checkpoint_lsn, recv_sys_struct::limit_lsn, LOG_ARCH_OFF, LOG_ARCHIVE, LOG_CHECKPOINT, LOG_CHECKPOINT_ARCHIVED_LSN, log_checkpoint_get_nth_group_info(), LOG_CHECKPOINT_LSN, LOG_CHECKPOINT_NO, LOG_FILE_HDR_SIZE, LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, log_group_get_capacity(), log_group_read_checkpoint_info(), log_struct::log_groups, log_sys, log_struct::lsn, mach_read_from_8(), memset, recv_sys_struct::mutex, log_struct::mutex, mutex_enter, mutex_exit(), log_struct::next_checkpoint_lsn, log_struct::next_checkpoint_no, OS_FILE_LOG, OS_FILE_LOG_BLOCK_SIZE, OS_FILE_READ, OS_FILE_WRITE, recv_sys_struct::parse_start_lsn, recv_sys_struct::recovered_lsn, recv_find_max_checkpoint(), recv_group_scan_log_recs(), recv_lsn_checks_on, recv_max_page_lsn, recv_needed_recovery, recv_recovery_on, recv_synchronize_groups(), recv_sys, recv_sys_create(), recv_sys_init(), recv_sys_struct::scanned_checkpoint_no, log_group_struct::scanned_lsn, recv_sys_struct::scanned_lsn, log_group_struct::space_id, SRV_FORCE_NO_LOG_REDO, srv_force_recovery, srv_start_lsn, TRUE, trx_sys_doublewrite_init_or_restore_pages(), ut_ad, ut_dulint_add(), ut_dulint_align_down(), ut_dulint_cmp(), ut_dulint_get_high(), ut_dulint_get_low(), ut_dulint_max, ut_error, UT_LIST_GET_FIRST, UT_LIST_GET_NEXT, ut_memcmp(), ut_memcpy(), ut_print_timestamp(), log_struct::written_to_all_lsn, and log_struct::written_to_some_lsn.
Referenced by innobase_start_or_create_for_mysql().
02576 : error code or DB_SUCCESS */ 02577 ulint type, /* in: LOG_CHECKPOINT or LOG_ARCHIVE */ 02578 dulint limit_lsn, /* in: recover up to this lsn if possible */ 02579 dulint min_flushed_lsn,/* in: min flushed lsn from data files */ 02580 dulint max_flushed_lsn)/* in: max flushed lsn from data files */ 02581 { 02582 log_group_t* group; 02583 log_group_t* max_cp_group; 02584 log_group_t* up_to_date_group; 02585 ulint max_cp_field; 02586 dulint checkpoint_lsn; 02587 dulint checkpoint_no; 02588 dulint old_scanned_lsn; 02589 dulint group_scanned_lsn; 02590 dulint contiguous_lsn; 02591 dulint archived_lsn; 02592 ulint capacity; 02593 byte* buf; 02594 byte log_hdr_buf[LOG_FILE_HDR_SIZE]; 02595 ulint err; 02596 02597 ut_ad((type != LOG_CHECKPOINT) 02598 || (ut_dulint_cmp(limit_lsn, ut_dulint_max) == 0)); 02599 02600 if (type == LOG_CHECKPOINT) { 02601 recv_sys_create(); 02602 recv_sys_init(FALSE, buf_pool_get_curr_size()); 02603 } 02604 02605 if (srv_force_recovery >= SRV_FORCE_NO_LOG_REDO) { 02606 fprintf(stderr, 02607 "InnoDB: The user has set SRV_FORCE_NO_LOG_REDO on\n"); 02608 fprintf(stderr, 02609 "InnoDB: Skipping log redo\n"); 02610 02611 return(DB_SUCCESS); 02612 } 02613 02614 recv_recovery_on = TRUE; 02615 02616 recv_sys->limit_lsn = limit_lsn; 02617 02618 mutex_enter(&(log_sys->mutex)); 02619 02620 /* Look for the latest checkpoint from any of the log groups */ 02621 02622 err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field); 02623 02624 if (err != DB_SUCCESS) { 02625 02626 mutex_exit(&(log_sys->mutex)); 02627 02628 return(err); 02629 } 02630 02631 log_group_read_checkpoint_info(max_cp_group, max_cp_field); 02632 02633 buf = log_sys->checkpoint_buf; 02634 02635 checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); 02636 checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); 02637 archived_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN); 02638 02639 /* Read the first log file header to print a note if this is 02640 a recovery from a restored InnoDB Hot Backup */ 02641 02642 fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, max_cp_group->space_id, 02643 0, 0, LOG_FILE_HDR_SIZE, 02644 log_hdr_buf, max_cp_group); 02645 02646 if (0 == ut_memcmp(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, 02647 (byte*)"ibbackup", (sizeof "ibbackup") - 1)) { 02648 /* This log file was created by ibbackup --restore: print 02649 a note to the user about it */ 02650 02651 fprintf(stderr, 02652 "InnoDB: The log file was created by ibbackup --apply-log at\n" 02653 "InnoDB: %s\n", log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP); 02654 fprintf(stderr, 02655 "InnoDB: NOTE: the following crash recovery is part of a normal restore.\n"); 02656 02657 /* Wipe over the label now */ 02658 02659 memset(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, 02660 ' ', 4); 02661 /* Write to the log file to wipe over the label */ 02662 fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, 02663 max_cp_group->space_id, 02664 0, 0, OS_FILE_LOG_BLOCK_SIZE, 02665 log_hdr_buf, max_cp_group); 02666 } 02667 02668 #ifdef UNIV_LOG_ARCHIVE 02669 group = UT_LIST_GET_FIRST(log_sys->log_groups); 02670 02671 while (group) { 02672 log_checkpoint_get_nth_group_info(buf, group->id, 02673 &(group->archived_file_no), 02674 &(group->archived_offset)); 02675 02676 group = UT_LIST_GET_NEXT(log_groups, group); 02677 } 02678 #endif /* UNIV_LOG_ARCHIVE */ 02679 02680 if (type == LOG_CHECKPOINT) { 02681 /* Start reading the log groups from the checkpoint lsn up. The 02682 variable contiguous_lsn contains an lsn up to which the log is 02683 known to be contiguously written to all log groups. */ 02684 02685 recv_sys->parse_start_lsn = checkpoint_lsn; 02686 recv_sys->scanned_lsn = checkpoint_lsn; 02687 recv_sys->scanned_checkpoint_no = 0; 02688 recv_sys->recovered_lsn = checkpoint_lsn; 02689 02690 srv_start_lsn = checkpoint_lsn; 02691 02692 /* NOTE: we always do a 'recovery' at startup, but only if 02693 there is something wrong we will print a message to the 02694 user about recovery: */ 02695 02696 if (ut_dulint_cmp(checkpoint_lsn, max_flushed_lsn) != 0 02697 || ut_dulint_cmp(checkpoint_lsn, min_flushed_lsn) != 0) { 02698 02699 if (ut_dulint_cmp(checkpoint_lsn, max_flushed_lsn) 02700 < 0) { 02701 fprintf(stderr, 02702 "InnoDB: ##########################################################\n" 02703 "InnoDB: WARNING!\n" 02704 "InnoDB: The log sequence number in ibdata files is higher\n" 02705 "InnoDB: than the log sequence number in the ib_logfiles! Are you sure\n" 02706 "InnoDB: you are using the right ib_logfiles to start up the database?\n" 02707 "InnoDB: Log sequence number in ib_logfiles is %lu %lu, log\n" 02708 "InnoDB: sequence numbers stamped to ibdata file headers are between\n" 02709 "InnoDB: %lu %lu and %lu %lu.\n" 02710 "InnoDB: ##########################################################\n", 02711 (ulong) ut_dulint_get_high(checkpoint_lsn), 02712 (ulong) ut_dulint_get_low(checkpoint_lsn), 02713 (ulong) ut_dulint_get_high(min_flushed_lsn), 02714 (ulong) ut_dulint_get_low(min_flushed_lsn), 02715 (ulong) ut_dulint_get_high(max_flushed_lsn), 02716 (ulong) ut_dulint_get_low(max_flushed_lsn)); 02717 } 02718 02719 recv_needed_recovery = TRUE; 02720 02721 ut_print_timestamp(stderr); 02722 02723 fprintf(stderr, 02724 " InnoDB: Database was not shut down normally!\n" 02725 "InnoDB: Starting crash recovery.\n"); 02726 02727 fprintf(stderr, 02728 "InnoDB: Reading tablespace information from the .ibd files...\n"); 02729 02730 fil_load_single_table_tablespaces(); 02731 02732 /* If we are using the doublewrite method, we will 02733 check if there are half-written pages in data files, 02734 and restore them from the doublewrite buffer if 02735 possible */ 02736 02737 if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { 02738 02739 fprintf(stderr, 02740 "InnoDB: Restoring possible half-written data pages from the doublewrite\n" 02741 "InnoDB: buffer...\n"); 02742 trx_sys_doublewrite_init_or_restore_pages( 02743 TRUE); 02744 } 02745 02746 ut_print_timestamp(stderr); 02747 02748 fprintf(stderr, 02749 " InnoDB: Starting log scan based on checkpoint at\n" 02750 "InnoDB: log sequence number %lu %lu.\n", 02751 (ulong) ut_dulint_get_high(checkpoint_lsn), 02752 (ulong) ut_dulint_get_low(checkpoint_lsn)); 02753 } else { 02754 /* Init the doublewrite buffer memory structure */ 02755 trx_sys_doublewrite_init_or_restore_pages(FALSE); 02756 } 02757 } 02758 02759 contiguous_lsn = ut_dulint_align_down(recv_sys->scanned_lsn, 02760 OS_FILE_LOG_BLOCK_SIZE); 02761 if (type == LOG_ARCHIVE) { 02762 /* Try to recover the remaining part from logs: first from 02763 the logs of the archived group */ 02764 02765 group = recv_sys->archive_group; 02766 capacity = log_group_get_capacity(group); 02767 02768 if ((ut_dulint_cmp(recv_sys->scanned_lsn, 02769 ut_dulint_add(checkpoint_lsn, capacity)) > 0) 02770 || (ut_dulint_cmp(checkpoint_lsn, 02771 ut_dulint_add(recv_sys->scanned_lsn, capacity)) > 0)) { 02772 02773 mutex_exit(&(log_sys->mutex)); 02774 02775 /* The group does not contain enough log: probably 02776 an archived log file was missing or corrupt */ 02777 02778 return(DB_ERROR); 02779 } 02780 02781 recv_group_scan_log_recs(group, &contiguous_lsn, 02782 &group_scanned_lsn); 02783 if (ut_dulint_cmp(recv_sys->scanned_lsn, checkpoint_lsn) < 0) { 02784 02785 mutex_exit(&(log_sys->mutex)); 02786 02787 /* The group did not contain enough log: an archived 02788 log file was missing or invalid, or the log group 02789 was corrupt */ 02790 02791 return(DB_ERROR); 02792 } 02793 02794 group->scanned_lsn = group_scanned_lsn; 02795 up_to_date_group = group; 02796 } else { 02797 up_to_date_group = max_cp_group; 02798 } 02799 02800 ut_ad(RECV_SCAN_SIZE <= log_sys->buf_size); 02801 02802 group = UT_LIST_GET_FIRST(log_sys->log_groups); 02803 02804 if ((type == LOG_ARCHIVE) && (group == recv_sys->archive_group)) { 02805 group = UT_LIST_GET_NEXT(log_groups, group); 02806 } 02807 02808 while (group) { 02809 old_scanned_lsn = recv_sys->scanned_lsn; 02810 02811 recv_group_scan_log_recs(group, &contiguous_lsn, 02812 &group_scanned_lsn); 02813 group->scanned_lsn = group_scanned_lsn; 02814 02815 if (ut_dulint_cmp(old_scanned_lsn, group_scanned_lsn) < 0) { 02816 /* We found a more up-to-date group */ 02817 02818 up_to_date_group = group; 02819 } 02820 02821 if ((type == LOG_ARCHIVE) 02822 && (group == recv_sys->archive_group)) { 02823 group = UT_LIST_GET_NEXT(log_groups, group); 02824 } 02825 02826 group = UT_LIST_GET_NEXT(log_groups, group); 02827 } 02828 02829 /* We currently have only one log group */ 02830 if (ut_dulint_cmp(group_scanned_lsn, checkpoint_lsn) < 0) { 02831 ut_print_timestamp(stderr); 02832 fprintf(stderr, 02833 " InnoDB: ERROR: We were only able to scan the log up to\n" 02834 "InnoDB: %lu %lu, but a checkpoint was at %lu %lu.\n" 02835 "InnoDB: It is possible that the database is now corrupt!\n", 02836 (ulong) ut_dulint_get_high(group_scanned_lsn), 02837 (ulong) ut_dulint_get_low(group_scanned_lsn), 02838 (ulong) ut_dulint_get_high(checkpoint_lsn), 02839 (ulong) ut_dulint_get_low(checkpoint_lsn)); 02840 } 02841 02842 if (ut_dulint_cmp(group_scanned_lsn, recv_max_page_lsn) < 0) { 02843 ut_print_timestamp(stderr); 02844 fprintf(stderr, 02845 " InnoDB: ERROR: We were only able to scan the log up to %lu %lu\n" 02846 "InnoDB: but a database page a had an lsn %lu %lu. It is possible that the\n" 02847 "InnoDB: database is now corrupt!\n", 02848 (ulong) ut_dulint_get_high(group_scanned_lsn), 02849 (ulong) ut_dulint_get_low(group_scanned_lsn), 02850 (ulong) ut_dulint_get_high(recv_max_page_lsn), 02851 (ulong) ut_dulint_get_low(recv_max_page_lsn)); 02852 } 02853 02854 if (ut_dulint_cmp(recv_sys->recovered_lsn, checkpoint_lsn) < 0) { 02855 02856 mutex_exit(&(log_sys->mutex)); 02857 02858 if (ut_dulint_cmp(recv_sys->recovered_lsn, limit_lsn) >= 0) { 02859 02860 return(DB_SUCCESS); 02861 } 02862 02863 ut_error; 02864 02865 return(DB_ERROR); 02866 } 02867 02868 /* Synchronize the uncorrupted log groups to the most up-to-date log 02869 group; we also copy checkpoint info to groups */ 02870 02871 log_sys->next_checkpoint_lsn = checkpoint_lsn; 02872 log_sys->next_checkpoint_no = ut_dulint_add(checkpoint_no, 1); 02873 02874 #ifdef UNIV_LOG_ARCHIVE 02875 log_sys->archived_lsn = archived_lsn; 02876 #endif /* UNIV_LOG_ARCHIVE */ 02877 02878 recv_synchronize_groups(up_to_date_group); 02879 02880 if (!recv_needed_recovery) { 02881 if (ut_dulint_cmp(checkpoint_lsn, recv_sys->recovered_lsn) 02882 != 0) { 02883 fprintf(stderr, 02884 "InnoDB: Warning: we did not need to do crash recovery, but log scan\n" 02885 "InnoDB: progressed past the checkpoint lsn %lu %lu up to lsn %lu %lu\n", 02886 (ulong) ut_dulint_get_high(checkpoint_lsn), 02887 (ulong) ut_dulint_get_low(checkpoint_lsn), 02888 (ulong) ut_dulint_get_high(recv_sys->recovered_lsn), 02889 (ulong) ut_dulint_get_low(recv_sys->recovered_lsn)); 02890 } 02891 } else { 02892 srv_start_lsn = recv_sys->recovered_lsn; 02893 } 02894 02895 log_sys->lsn = recv_sys->recovered_lsn; 02896 02897 ut_memcpy(log_sys->buf, recv_sys->last_block, OS_FILE_LOG_BLOCK_SIZE); 02898 02899 log_sys->buf_free = ut_dulint_get_low(log_sys->lsn) 02900 % OS_FILE_LOG_BLOCK_SIZE; 02901 log_sys->buf_next_to_write = log_sys->buf_free; 02902 log_sys->written_to_some_lsn = log_sys->lsn; 02903 log_sys->written_to_all_lsn = log_sys->lsn; 02904 02905 log_sys->last_checkpoint_lsn = checkpoint_lsn; 02906 02907 log_sys->next_checkpoint_no = ut_dulint_add(checkpoint_no, 1); 02908 02909 #ifdef UNIV_LOG_ARCHIVE 02910 if (ut_dulint_cmp(archived_lsn, ut_dulint_max) == 0) { 02911 02912 log_sys->archiving_state = LOG_ARCH_OFF; 02913 } 02914 #endif /* UNIV_LOG_ARCHIVE */ 02915 02916 mutex_enter(&(recv_sys->mutex)); 02917 02918 recv_sys->apply_log_recs = TRUE; 02919 02920 mutex_exit(&(recv_sys->mutex)); 02921 02922 mutex_exit(&(log_sys->mutex)); 02923 02924 recv_lsn_checks_on = TRUE; 02925 02926 /* The database is now ready to start almost normal processing of user 02927 transactions: transaction rollbacks and the application of the log 02928 records in the hash table can be run in background. */ 02929 02930 return(DB_SUCCESS); 02931 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1920 of file log0recv.c.
References recv_sys_struct::buf, recv_sys_struct::recovered_lsn, recv_previous_parsed_rec_is_multi, recv_previous_parsed_rec_offset, recv_previous_parsed_rec_type, recv_sys, ut_dulint_get_high(), ut_dulint_get_low(), and ut_print_buf().
Referenced by recv_parse_log_recs().
01922 : pointer to corrupt log record */ 01923 byte type, /* in: type of the record */ 01924 ulint space, /* in: space id, this may also be garbage */ 01925 ulint page_no)/* in: page number, this may also be garbage */ 01926 { 01927 fprintf(stderr, 01928 "InnoDB: ############### CORRUPT LOG RECORD FOUND\n" 01929 "InnoDB: Log record type %lu, space id %lu, page number %lu\n" 01930 "InnoDB: Log parsing proceeded successfully up to %lu %lu\n" 01931 "InnoDB: Previous log record type %lu, is multi %lu\n" 01932 "InnoDB: Recv offset %lu, prev %lu\n", 01933 (ulong) type, (ulong) space, (ulong) page_no, 01934 (ulong) ut_dulint_get_high(recv_sys->recovered_lsn), 01935 (ulong) ut_dulint_get_low(recv_sys->recovered_lsn), 01936 (ulong) recv_previous_parsed_rec_type, 01937 (ulong) recv_previous_parsed_rec_is_multi, 01938 (ulong) (ptr - recv_sys->buf), 01939 (ulong) recv_previous_parsed_rec_offset); 01940 01941 if ((ulint)(ptr - recv_sys->buf + 100) 01942 > recv_previous_parsed_rec_offset 01943 && (ulint)(ptr - recv_sys->buf + 100 01944 - recv_previous_parsed_rec_offset) 01945 < 200000) { 01946 fputs( 01947 "InnoDB: Hex dump of corrupt log starting 100 bytes before the start\n" 01948 "InnoDB: of the previous log rec,\n" 01949 "InnoDB: and ending 100 bytes after the start of the corrupt rec:\n", 01950 stderr); 01951 01952 ut_print_buf(stderr, 01953 recv_sys->buf + recv_previous_parsed_rec_offset - 100, 01954 ptr - recv_sys->buf + 200 - 01955 recv_previous_parsed_rec_offset); 01956 putc('\n', stderr); 01957 } 01958 01959 fputs( 01960 "InnoDB: WARNING: the log file may have been corrupt and it\n" 01961 "InnoDB: is possible that the log scan did not proceed\n" 01962 "InnoDB: far enough in recovery! Please run CHECK TABLE\n" 01963 "InnoDB: on your InnoDB tables to check that they are ok!\n" 01964 "InnoDB: If mysqld crashes after this recovery, look at\n" 01965 "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n" 01966 "InnoDB: about forcing recovery.\n", stderr); 01967 01968 fflush(stderr); 01969 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void recv_reset_logs | ( | dulint | lsn, | |
| ibool | new_logs_created | |||
| ) |
Definition at line 2992 of file log0recv.c.
References log_group_struct::archived_file_no, log_struct::archived_lsn, log_group_struct::archived_offset, log_struct::buf, log_struct::buf_free, log_struct::buf_next_to_write, log_struct::last_checkpoint_lsn, LOG_BLOCK_HDR_SIZE, log_block_init(), log_block_set_first_rec_group(), LOG_FILE_HDR_SIZE, log_struct::log_groups, log_make_checkpoint_at(), log_sys, log_group_struct::lsn, log_struct::lsn, log_group_struct::lsn_offset, log_struct::mutex, mutex_enter, mutex_exit(), log_struct::next_checkpoint_no, OS_FILE_LOG_BLOCK_SIZE, recv_truncate_group(), TRUE, ut_ad, ut_dulint_add(), ut_dulint_align_up(), ut_dulint_max, ut_dulint_zero, UT_LIST_GET_FIRST, UT_LIST_GET_NEXT, log_struct::written_to_all_lsn, and log_struct::written_to_some_lsn.
Referenced by innobase_start_or_create_for_mysql().
02994 : reset to this lsn rounded up to 02995 be divisible by OS_FILE_LOG_BLOCK_SIZE, 02996 after which we add LOG_BLOCK_HDR_SIZE */ 02997 #ifdef UNIV_LOG_ARCHIVE 02998 ulint arch_log_no, /* in: next archived log file number */ 02999 #endif /* UNIV_LOG_ARCHIVE */ 03000 ibool new_logs_created)/* in: TRUE if resetting logs is done 03001 at the log creation; FALSE if it is done 03002 after archive recovery */ 03003 { 03004 log_group_t* group; 03005 03006 #ifdef UNIV_SYNC_DEBUG 03007 ut_ad(mutex_own(&(log_sys->mutex))); 03008 #endif /* UNIV_SYNC_DEBUG */ 03009 log_sys->lsn = ut_dulint_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE); 03010 03011 group = UT_LIST_GET_FIRST(log_sys->log_groups); 03012 03013 while (group) { 03014 group->lsn = log_sys->lsn; 03015 group->lsn_offset = LOG_FILE_HDR_SIZE; 03016 #ifdef UNIV_LOG_ARCHIVE 03017 group->archived_file_no = arch_log_no; 03018 group->archived_offset = 0; 03019 #endif /* UNIV_LOG_ARCHIVE */ 03020 03021 if (!new_logs_created) { 03022 recv_truncate_group(group, group->lsn, group->lsn, 03023 group->lsn, group->lsn); 03024 } 03025 03026 group = UT_LIST_GET_NEXT(log_groups, group); 03027 } 03028 03029 log_sys->buf_next_to_write = 0; 03030 log_sys->written_to_some_lsn = log_sys->lsn; 03031 log_sys->written_to_all_lsn = log_sys->lsn; 03032 03033 log_sys->next_checkpoint_no = ut_dulint_zero; 03034 log_sys->last_checkpoint_lsn = ut_dulint_zero; 03035 03036 #ifdef UNIV_LOG_ARCHIVE 03037 log_sys->archived_lsn = log_sys->lsn; 03038 #endif /* UNIV_LOG_ARCHIVE */ 03039 03040 log_block_init(log_sys->buf, log_sys->lsn); 03041 log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE); 03042 03043 log_sys->buf_free = LOG_BLOCK_HDR_SIZE; 03044 log_sys->lsn = ut_dulint_add(log_sys->lsn, LOG_BLOCK_HDR_SIZE); 03045 03046 mutex_exit(&(log_sys->mutex)); 03047 03048 /* Reset the checkpoint fields in logs */ 03049 03050 log_make_checkpoint_at(ut_dulint_max, TRUE); 03051 log_make_checkpoint_at(ut_dulint_max, TRUE); 03052 03053 mutex_enter(&(log_sys->mutex)); 03054 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool recv_scan_log_recs | ( | ibool | apply_automatically, | |
| ulint | available_memory, | |||
| ibool | store_to_hash, | |||
| byte * | buf, | |||
| ulint | len, | |||
| dulint | start_lsn, | |||
| dulint * | contiguous_lsn, | |||
| dulint * | group_scanned_lsn | |||
| ) |
Definition at line 2320 of file log0recv.c.
References FALSE, yaSSL::finished, recv_sys_struct::found_corrupt_log, recv_sys_struct::heap, recv_sys_struct::len, log_block_calc_checksum(), log_block_checksum_is_ok_or_old_format(), log_block_convert_lsn_to_no(), log_block_get_checkpoint_no(), log_block_get_checksum(), log_block_get_data_len(), log_block_get_first_rec_group(), log_block_get_flush_bit(), log_block_get_hdr_no(), mem_heap_get_size(), OS_FILE_LOG_BLOCK_SIZE, recv_sys_struct::parse_start_lsn, recv_sys_struct::recovered_lsn, recv_sys_struct::recovered_offset, recv_apply_hashed_log_recs(), recv_is_from_backup, recv_is_making_a_backup, recv_needed_recovery, recv_parse_log_recs(), RECV_PARSING_BUF_SIZE, recv_scan_print_counter, recv_sys, recv_sys_add_to_parsing_buf(), recv_sys_justify_left_parsing_buf(), recv_sys_struct::scanned_checkpoint_no, recv_sys_struct::scanned_lsn, TRUE, ut_a, ut_ad, ut_dulint_add(), ut_dulint_cmp(), ut_dulint_get_high(), ut_dulint_get_low(), ut_dulint_is_zero(), and ut_error.
Referenced by log_check_log_recs(), and recv_group_scan_log_recs().
02322 : TRUE if limit_lsn has been reached, or 02323 not able to scan any more in this log group */ 02324 ibool apply_automatically,/* in: TRUE if we want this function to 02325 apply log records automatically when the 02326 hash table becomes full; in the hot backup tool 02327 the tool does the applying, not this 02328 function */ 02329 ulint available_memory,/* in: we let the hash table of recs to grow 02330 to this size, at the maximum */ 02331 ibool store_to_hash, /* in: TRUE if the records should be stored 02332 to the hash table; this is set to FALSE if just 02333 debug checking is needed */ 02334 byte* buf, /* in: buffer containing a log segment or 02335 garbage */ 02336 ulint len, /* in: buffer length */ 02337 dulint start_lsn, /* in: buffer start lsn */ 02338 dulint* contiguous_lsn, /* in/out: it is known that all log groups 02339 contain contiguous log data up to this lsn */ 02340 dulint* group_scanned_lsn)/* out: scanning succeeded up to this lsn */ 02341 { 02342 byte* log_block; 02343 ulint no; 02344 dulint scanned_lsn; 02345 ibool finished; 02346 ulint data_len; 02347 ibool more_data; 02348 02349 ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0); 02350 ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0); 02351 ut_ad(len > 0); 02352 ut_a(apply_automatically <= TRUE); 02353 ut_a(store_to_hash <= TRUE); 02354 02355 finished = FALSE; 02356 02357 log_block = buf; 02358 scanned_lsn = start_lsn; 02359 more_data = FALSE; 02360 02361 while (log_block < buf + len && !finished) { 02362 02363 no = log_block_get_hdr_no(log_block); 02364 /* 02365 fprintf(stderr, "Log block header no %lu\n", no); 02366 02367 fprintf(stderr, "Scanned lsn no %lu\n", 02368 log_block_convert_lsn_to_no(scanned_lsn)); 02369 */ 02370 if (no != log_block_convert_lsn_to_no(scanned_lsn) 02371 || !log_block_checksum_is_ok_or_old_format(log_block)) { 02372 02373 if (no == log_block_convert_lsn_to_no(scanned_lsn) 02374 && !log_block_checksum_is_ok_or_old_format( 02375 log_block)) { 02376 fprintf(stderr, 02377 "InnoDB: Log block no %lu at lsn %lu %lu has\n" 02378 "InnoDB: ok header, but checksum field contains %lu, should be %lu\n", 02379 (ulong) no, 02380 (ulong) ut_dulint_get_high(scanned_lsn), 02381 (ulong) ut_dulint_get_low(scanned_lsn), 02382 (ulong) log_block_get_checksum(log_block), 02383 (ulong) log_block_calc_checksum(log_block)); 02384 } 02385 02386 /* Garbage or an incompletely written log block */ 02387 02388 finished = TRUE; 02389 02390 break; 02391 } 02392 02393 if (log_block_get_flush_bit(log_block)) { 02394 /* This block was a start of a log flush operation: 02395 we know that the previous flush operation must have 02396 been completed for all log groups before this block 02397 can have been flushed to any of the groups. Therefore, 02398 we know that log data is contiguous up to scanned_lsn 02399 in all non-corrupt log groups. */ 02400 02401 if (ut_dulint_cmp(scanned_lsn, *contiguous_lsn) > 0) { 02402 *contiguous_lsn = scanned_lsn; 02403 } 02404 } 02405 02406 data_len = log_block_get_data_len(log_block); 02407 02408 if ((store_to_hash || (data_len == OS_FILE_LOG_BLOCK_SIZE)) 02409 && (ut_dulint_cmp(ut_dulint_add(scanned_lsn, data_len), 02410 recv_sys->scanned_lsn) > 0) 02411 && (recv_sys->scanned_checkpoint_no > 0) 02412 && (log_block_get_checkpoint_no(log_block) 02413 < recv_sys->scanned_checkpoint_no) 02414 && (recv_sys->scanned_checkpoint_no 02415 - log_block_get_checkpoint_no(log_block) 02416 > 0x80000000UL)) { 02417 02418 /* Garbage from a log buffer flush which was made 02419 before the most recent database recovery */ 02420 02421 finished = TRUE; 02422 #ifdef UNIV_LOG_DEBUG 02423 /* This is not really an error, but currently 02424 we stop here in the debug version: */ 02425 02426 ut_error; 02427 #endif 02428 break; 02429 } 02430 02431 if (ut_dulint_is_zero(recv_sys->parse_start_lsn) 02432 && (log_block_get_first_rec_group(log_block) > 0)) { 02433 02434 /* We found a point from which to start the parsing 02435 of log records */ 02436 02437 recv_sys->parse_start_lsn = 02438 ut_dulint_add(scanned_lsn, 02439 log_block_get_first_rec_group(log_block)); 02440 recv_sys->scanned_lsn = recv_sys->parse_start_lsn; 02441 recv_sys->recovered_lsn = recv_sys->parse_start_lsn; 02442 } 02443 02444 scanned_lsn = ut_dulint_add(scanned_lsn, data_len); 02445 02446 if (ut_dulint_cmp(scanned_lsn, recv_sys->scanned_lsn) > 0) { 02447 02448 /* We were able to find more log data: add it to the 02449 parsing buffer if parse_start_lsn is already 02450 non-zero */ 02451 02452 if (recv_sys->len + 4 * OS_FILE_LOG_BLOCK_SIZE 02453 >= RECV_PARSING_BUF_SIZE) { 02454 fprintf(stderr, 02455 "InnoDB: Error: log parsing buffer overflow. Recovery may have failed!\n"); 02456 02457 recv_sys->found_corrupt_log = TRUE; 02458 02459 } else if (!recv_sys->found_corrupt_log) { 02460 more_data = recv_sys_add_to_parsing_buf( 02461 log_block, scanned_lsn); 02462 } 02463 02464 recv_sys->scanned_lsn = scanned_lsn; 02465 recv_sys->scanned_checkpoint_no = 02466 log_block_get_checkpoint_no(log_block); 02467 } 02468 02469 if (data_len < OS_FILE_LOG_BLOCK_SIZE) { 02470 /* Log data for this group ends here */ 02471 02472 finished = TRUE; 02473 } else { 02474 log_block += OS_FILE_LOG_BLOCK_SIZE; 02475 } 02476 } 02477 02478 *group_scanned_lsn = scanned_lsn; 02479 02480 if (recv_needed_recovery 02481 || (recv_is_from_backup && !recv_is_making_a_backup)) { 02482 recv_scan_print_counter++; 02483 02484 if (finished || (recv_scan_print_counter % 80 == 0)) { 02485 02486 fprintf(stderr, 02487 "InnoDB: Doing recovery: scanned up to log sequence number %lu %lu\n", 02488 (ulong) ut_dulint_get_high(*group_scanned_lsn), 02489 (ulong) ut_dulint_get_low(*group_scanned_lsn)); 02490 } 02491 } 02492 02493 if (more_data && !recv_sys->found_corrupt_log) { 02494 /* Try to parse more log records */ 02495 02496 recv_parse_log_recs(store_to_hash); 02497 02498 if (store_to_hash && mem_heap_get_size(recv_sys->heap) 02499 > available_memory 02500 && apply_automatically) { 02501 02502 /* Hash table of log records has grown too big: 02503 empty it; FALSE means no ibuf operations 02504 allowed, as we cannot add new records to the 02505 log yet: they would be produced by ibuf 02506 operations */ 02507 02508 recv_apply_hashed_log_recs(FALSE); 02509 } 02510 02511 if (recv_sys->recovered_offset > RECV_PARSING_BUF_SIZE / 4) { 02512 /* Move parsing buffer data to the buffer start */ 02513 02514 recv_sys_justify_left_parsing_buf(); 02515 } 02516 } 02517 02518 return(finished); 02519 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void recv_scan_log_seg_for_backup | ( | byte * | buf, | |
| ulint | buf_len, | |||
| dulint * | scanned_lsn, | |||
| ulint * | scanned_checkpoint_no, | |||
| ulint * | n_bytes_scanned | |||
| ) |
Definition at line 661 of file log0recv.c.
References log_block_checksum_is_ok_or_old_format(), log_block_convert_lsn_to_no(), log_block_get_checkpoint_no(), log_block_get_data_len(), log_block_get_hdr_no(), OS_FILE_LOG_BLOCK_SIZE, and ut_dulint_add().
00663 : buffer containing log data */ 00664 ulint buf_len, /* in: data length in that buffer */ 00665 dulint* scanned_lsn, /* in/out: lsn of buffer start, 00666 we return scanned lsn */ 00667 ulint* scanned_checkpoint_no, 00668 /* in/out: 4 lowest bytes of the 00669 highest scanned checkpoint number so 00670 far */ 00671 ulint* n_bytes_scanned)/* out: how much we were able to 00672 scan, smaller than buf_len if log 00673 data ended here */ 00674 { 00675 ulint data_len; 00676 byte* log_block; 00677 ulint no; 00678 00679 *n_bytes_scanned = 0; 00680 00681 for (log_block = buf; log_block < buf + buf_len; 00682 log_block += OS_FILE_LOG_BLOCK_SIZE) { 00683 00684 no = log_block_get_hdr_no(log_block); 00685 00686 /* fprintf(stderr, "Log block header no %lu\n", no); */ 00687 00688 if (no != log_block_convert_lsn_to_no(*scanned_lsn) 00689 || !log_block_checksum_is_ok_or_old_format(log_block)) { 00690 /* 00691 fprintf(stderr, 00692 "Log block n:o %lu, scanned lsn n:o %lu\n", 00693 no, log_block_convert_lsn_to_no(*scanned_lsn)); 00694 */ 00695 /* Garbage or an incompletely written log block */ 00696 00697 log_block += OS_FILE_LOG_BLOCK_SIZE; 00698 /* 00699 fprintf(stderr, 00700 "Next log block n:o %lu\n", 00701 log_block_get_hdr_no(log_block)); 00702 */ 00703 break; 00704 } 00705 00706 if (*scanned_checkpoint_no > 0 00707 && log_block_get_checkpoint_no(log_block) 00708 < *scanned_checkpoint_no 00709 && *scanned_checkpoint_no 00710 - log_block_get_checkpoint_no(log_block) 00711 > 0x80000000UL) { 00712 00713 /* Garbage from a log buffer flush which was made 00714 before the most recent database recovery */ 00715 /* 00716 fprintf(stderr, 00717 "Scanned cp n:o %lu, block cp n:o %lu\n", 00718 *scanned_checkpoint_no, 00719 log_block_get_checkpoint_no(log_block)); 00720 */ 00721 break; 00722 } 00723 00724 data_len = log_block_get_data_len(log_block); 00725 00726 *scanned_checkpoint_no 00727 = log_block_get_checkpoint_no(log_block); 00728 *scanned_lsn = ut_dulint_add(*scanned_lsn, data_len); 00729 00730 *n_bytes_scanned += data_len; 00731 00732 if (data_len < OS_FILE_LOG_BLOCK_SIZE) { 00733 /* Log data ends here */ 00734 00735 /* fprintf(stderr, "Log block data len %lu\n", 00736 data_len); */ 00737 00738 break; 00739 } 00740 } 00741 }
Here is the call graph for this function:

| static void recv_synchronize_groups | ( | log_group_t * | up_to_date_group | ) | [static] |
Definition at line 368 of file log0recv.c.
References log_struct::checkpoint_lock, recv_sys_struct::last_block, recv_sys_struct::limit_lsn, log_group_read_log_seg(), log_group_set_fields(), log_struct::log_groups, log_groups_write_checkpoint_info(), LOG_RECOVER, log_sys, log_struct::mutex, mutex_enter, mutex_exit(), OS_FILE_LOG_BLOCK_SIZE, recv_sys_struct::recovered_lsn, recv_copy_group(), recv_sys, rw_lock_s_lock, rw_lock_s_unlock, ut_a, ut_dulint_align_down(), ut_dulint_align_up(), ut_dulint_cmp(), UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by recv_recovery_from_checkpoint_start().
00370 : the most up-to-date 00371 log group */ 00372 { 00373 log_group_t* group; 00374 dulint start_lsn; 00375 dulint end_lsn; 00376 dulint recovered_lsn; 00377 dulint limit_lsn; 00378 00379 recovered_lsn = recv_sys->recovered_lsn; 00380 limit_lsn = recv_sys->limit_lsn; 00381 00382 /* Read the last recovered log block to the recovery system buffer: 00383 the block is always incomplete */ 00384 00385 start_lsn = ut_dulint_align_down(recovered_lsn, 00386 OS_FILE_LOG_BLOCK_SIZE); 00387 end_lsn = ut_dulint_align_up(recovered_lsn, OS_FILE_LOG_BLOCK_SIZE); 00388 00389 ut_a(ut_dulint_cmp(start_lsn, end_lsn) != 0); 00390 00391 log_group_read_log_seg(LOG_RECOVER, recv_sys->last_block, 00392 up_to_date_group, start_lsn, end_lsn); 00393 00394 group = UT_LIST_GET_FIRST(log_sys->log_groups); 00395 00396 while (group) { 00397 if (group != up_to_date_group) { 00398 00399 /* Copy log data if needed */ 00400 00401 recv_copy_group(group, up_to_date_group, 00402 recovered_lsn); 00403 } 00404 00405 /* Update the fields in the group struct to correspond to 00406 recovered_lsn */ 00407 00408 log_group_set_fields(group, recovered_lsn); 00409 00410 group = UT_LIST_GET_NEXT(log_groups, group); 00411 } 00412 00413 /* Copy the checkpoint info to the groups; remember that we have 00414 incremented checkpoint_no by one, and the info will not be written 00415 over the max checkpoint info, thus making the preservation of max 00416 checkpoint info on disk certain */ 00417 00418 log_groups_write_checkpoint_info(); 00419 00420 mutex_exit(&(log_sys->mutex)); 00421 00422 /* Wait for the checkpoint write to complete */ 00423 rw_lock_s_lock(&(log_sys->checkpoint_lock)); 00424 rw_lock_s_unlock(&(log_sys->checkpoint_lock)); 00425 00426 mutex_enter(&(log_sys->mutex)); 00427 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2228 of file log0recv.c.
References recv_sys_struct::buf, FALSE, recv_sys_struct::len, log_block_get_data_len(), LOG_BLOCK_HDR_SIZE, LOG_BLOCK_TRL_SIZE, OS_FILE_LOG_BLOCK_SIZE, recv_sys_struct::parse_start_lsn, RECV_PARSING_BUF_SIZE, recv_sys, recv_sys_struct::scanned_lsn, start_offset, TRUE, ut_a, ut_ad, ut_dulint_cmp(), ut_dulint_is_zero(), ut_dulint_minus(), and ut_memcpy().
Referenced by recv_scan_log_recs().
02230 : TRUE if more data added */ 02231 byte* log_block, /* in: log block */ 02232 dulint scanned_lsn) /* in: lsn of how far we were able to find 02233 data in this log block */ 02234 { 02235 ulint more_len; 02236 ulint data_len; 02237 ulint start_offset; 02238 ulint end_offset; 02239 02240 ut_ad(ut_dulint_cmp(scanned_lsn, recv_sys->scanned_lsn) >= 0); 02241 02242 if (ut_dulint_is_zero(recv_sys->parse_start_lsn)) { 02243 /* Cannot start parsing yet because no start point for 02244 it found */ 02245 02246 return(FALSE); 02247 } 02248 02249 data_len = log_block_get_data_len(log_block); 02250 02251 if (ut_dulint_cmp(recv_sys->parse_start_lsn, scanned_lsn) >= 0) { 02252 02253 return(FALSE); 02254 02255 } else if (ut_dulint_cmp(recv_sys->scanned_lsn, scanned_lsn) >= 0) { 02256 02257 return(FALSE); 02258 02259 } else if (ut_dulint_cmp(recv_sys->parse_start_lsn, 02260 recv_sys->scanned_lsn) > 0) { 02261 more_len = ut_dulint_minus(scanned_lsn, 02262 recv_sys->parse_start_lsn); 02263 } else { 02264 more_len = ut_dulint_minus(scanned_lsn, recv_sys->scanned_lsn); 02265 } 02266 02267 if (more_len == 0) { 02268 02269 return(FALSE); 02270 } 02271 02272 ut_ad(data_len >= more_len); 02273 02274 start_offset = data_len - more_len; 02275 02276 if (start_offset < LOG_BLOCK_HDR_SIZE) { 02277 start_offset = LOG_BLOCK_HDR_SIZE; 02278 } 02279 02280 end_offset = data_len; 02281 02282 if (end_offset > OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { 02283 end_offset = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; 02284 } 02285 02286 ut_ad(start_offset <= end_offset); 02287 02288 if (start_offset < end_offset) { 02289 ut_memcpy(recv_sys->buf + recv_sys->len, 02290 log_block + start_offset, end_offset - start_offset); 02291 02292 recv_sys->len += end_offset - start_offset; 02293 02294 ut_a(recv_sys->len <= RECV_PARSING_BUF_SIZE); 02295 } 02296 02297 return(TRUE); 02298 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void recv_sys_create | ( | void | ) |
Definition at line 105 of file log0recv.c.
References recv_sys_struct::addr_hash, recv_sys_struct::heap, mem_alloc, recv_sys_struct::mutex, mutex_create, NULL, recv_sys, and SYNC_RECV.
Referenced by log_init(), and recv_recovery_from_checkpoint_start().
00107 { 00108 if (recv_sys != NULL) { 00109 00110 return; 00111 } 00112 00113 recv_sys = mem_alloc(sizeof(recv_sys_t)); 00114 00115 mutex_create(&recv_sys->mutex, SYNC_RECV); 00116 00117 recv_sys->heap = NULL; 00118 recv_sys->addr_hash = NULL; 00119 }
Here is the caller graph for this function:

| static void recv_sys_empty_hash | ( | void | ) | [static] |
Definition at line 170 of file log0recv.c.
References recv_sys_struct::addr_hash, buf_pool_get_curr_size(), hash_create(), hash_table_free(), recv_sys_struct::heap, mem_heap_empty(), recv_sys_struct::mutex, recv_sys_struct::n_addrs, recv_max_parsed_page_no, recv_sys, ut_ad, and ut_error.
Referenced by recv_apply_hashed_log_recs().
00172 { 00173 #ifdef UNIV_SYNC_DEBUG 00174 ut_ad(mutex_own(&(recv_sys->mutex))); 00175 #endif /* UNIV_SYNC_DEBUG */ 00176 if (recv_sys->n_addrs != 0) { 00177 fprintf(stderr, 00178 "InnoDB: Error: %lu pages with log records were left unprocessed!\n" 00179 "InnoDB: Maximum page number with log records on it %lu\n", 00180 (ulong) recv_sys->n_addrs, 00181 (ulong) recv_max_parsed_page_no); 00182 ut_error; 00183 } 00184 00185 hash_table_free(recv_sys->addr_hash); 00186 mem_heap_empty(recv_sys->heap); 00187 00188 recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 256); 00189 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void recv_sys_free | ( | void | ) | [static] |
Definition at line 195 of file log0recv.c.
References recv_sys_struct::addr_hash, recv_sys_struct::buf, hash_table_free(), recv_sys_struct::heap, recv_sys_struct::last_block_buf_start, mem_free, mem_heap_free, recv_sys_struct::mutex, mutex_enter, mutex_exit(), NULL, recv_sys, and ut_free().
Referenced by recv_recovery_from_checkpoint_finish().
00197 { 00198 mutex_enter(&(recv_sys->mutex)); 00199 00200 hash_table_free(recv_sys->addr_hash); 00201 mem_heap_free(recv_sys->heap); 00202 ut_free(recv_sys->buf); 00203 mem_free(recv_sys->last_block_buf_start); 00204 00205 recv_sys->addr_hash = NULL; 00206 recv_sys->heap = NULL; 00207 00208 mutex_exit(&(recv_sys->mutex)); 00209 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void recv_sys_init | ( | ibool | recover_from_backup, | |
| ulint | available_memory | |||
| ) |
Definition at line 125 of file log0recv.c.
References recv_sys_struct::addr_hash, recv_sys_struct::apply_batch_on, recv_sys_struct::apply_log_recs, recv_sys_struct::buf, FALSE, recv_sys_struct::found_corrupt_log, hash_create(), recv_sys_struct::heap, recv_sys_struct::last_block, recv_sys_struct::last_block_buf_start, recv_sys_struct::len, mem_alloc, mem_heap_create, mem_heap_create_in_buffer, recv_sys_struct::mutex, mutex_enter, mutex_exit(), recv_sys_struct::n_addrs, NULL, OS_FILE_LOG_BLOCK_SIZE, recv_sys_struct::recovered_offset, recv_is_from_backup, recv_max_page_lsn, RECV_PARSING_BUF_SIZE, recv_sys, TRUE, ut_align(), ut_dulint_zero, and ut_malloc().
Referenced by log_init(), and recv_recovery_from_checkpoint_start().
00127 : TRUE if this is called 00128 to recover from a hot backup */ 00129 ulint available_memory) /* in: available memory in bytes */ 00130 { 00131 if (recv_sys->heap != NULL) { 00132 00133 return; 00134 } 00135 00136 mutex_enter(&(recv_sys->mutex)); 00137 00138 if (!recover_from_backup) { 00139 recv_sys->heap = mem_heap_create_in_buffer(256); 00140 } else { 00141 recv_sys->heap = mem_heap_create(256); 00142 recv_is_from_backup = TRUE; 00143 } 00144 00145 recv_sys->buf = ut_malloc(RECV_PARSING_BUF_SIZE); 00146 recv_sys->len = 0; 00147 recv_sys->recovered_offset = 0; 00148 00149 recv_sys->addr_hash = hash_create(available_memory / 64); 00150 recv_sys->n_addrs = 0; 00151 00152 recv_sys->apply_log_recs = FALSE; 00153 recv_sys->apply_batch_on = FALSE; 00154 00155 recv_sys->last_block_buf_start = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE); 00156 00157 recv_sys->last_block = ut_align(recv_sys->last_block_buf_start, 00158 OS_FILE_LOG_BLOCK_SIZE); 00159 recv_sys->found_corrupt_log = FALSE; 00160 00161 recv_max_page_lsn = ut_dulint_zero; 00162 00163 mutex_exit(&(recv_sys->mutex)); 00164 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void recv_sys_justify_left_parsing_buf | ( | void | ) | [static] |
Definition at line 2304 of file log0recv.c.
References recv_sys_struct::buf, recv_sys_struct::len, recv_sys_struct::recovered_offset, recv_sys, and ut_memmove().
Referenced by recv_scan_log_recs().
02306 { 02307 ut_memmove(recv_sys->buf, recv_sys->buf + recv_sys->recovered_offset, 02308 recv_sys->len - recv_sys->recovered_offset); 02309 02310 recv_sys->len -= recv_sys->recovered_offset; 02311 02312 recv_sys->recovered_offset = 0; 02313 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void recv_truncate_group | ( | log_group_t * | group, | |
| dulint | recovered_lsn, | |||
| dulint | limit_lsn, | |||
| dulint | checkpoint_lsn, | |||
| dulint | archived_lsn | |||
| ) | [static] |
Definition at line 215 of file log0recv.c.
References log_struct::buf, recv_sys_struct::last_block, recv_sys_struct::last_log_buf_size, log_block_set_data_len(), log_group_get_capacity(), log_group_write_buf(), log_sys, OS_FILE_LOG_BLOCK_SIZE, RECV_SCAN_SIZE, recv_sys, ut_a, ut_dulint_add(), ut_dulint_align_down(), ut_dulint_align_up(), ut_dulint_cmp(), ut_dulint_get_min(), ut_dulint_max, ut_dulint_minus(), and ut_memcpy().
Referenced by recv_reset_logs().
00217 : log group */ 00218 dulint recovered_lsn, /* in: recovery succeeded up to this 00219 lsn */ 00220 dulint limit_lsn, /* in: this was the limit for 00221 recovery */ 00222 dulint checkpoint_lsn, /* in: recovery was started from this 00223 checkpoint */ 00224 dulint archived_lsn) /* in: the log has been archived up to 00225 this lsn */ 00226 { 00227 dulint start_lsn; 00228 dulint end_lsn; 00229 dulint finish_lsn1; 00230 dulint finish_lsn2; 00231 dulint finish_lsn; 00232 ulint len; 00233 ulint i; 00234 00235 if (ut_dulint_cmp(archived_lsn, ut_dulint_max) == 0) { 00236 /* Checkpoint was taken in the NOARCHIVELOG mode */ 00237 archived_lsn = checkpoint_lsn; 00238 } 00239 00240 finish_lsn1 = ut_dulint_add(ut_dulint_align_down(archived_lsn, 00241 OS_FILE_LOG_BLOCK_SIZE), 00242 log_group_get_capacity(group)); 00243 00244 finish_lsn2 = ut_dulint_add(ut_dulint_align_up(recovered_lsn, 00245 OS_FILE_LOG_BLOCK_SIZE), 00246 recv_sys->last_log_buf_size); 00247 00248 if (ut_dulint_cmp(limit_lsn, ut_dulint_max) != 0) { 00249 /* We do not know how far we should erase log records: erase 00250 as much as possible */ 00251 00252 finish_lsn = finish_lsn1; 00253 } else { 00254 /* It is enough to erase the length of the log buffer */ 00255 finish_lsn = ut_dulint_get_min(finish_lsn1, finish_lsn2); 00256 } 00257 00258 ut_a(RECV_SCAN_SIZE <= log_sys->buf_size); 00259 00260 /* Write the log buffer full of zeros */ 00261 for (i = 0; i < RECV_SCAN_SIZE; i++) { 00262 00263 *(log_sys->buf + i) = '\0'; 00264 } 00265 00266 start_lsn = ut_dulint_align_down(recovered_lsn, 00267 OS_FILE_LOG_BLOCK_SIZE); 00268 00269 if (ut_dulint_cmp(start_lsn, recovered_lsn) != 0) { 00270 /* Copy the last incomplete log block to the log buffer and 00271 edit its data length: */ 00272 00273 ut_memcpy(log_sys->buf, recv_sys->last_block, 00274 OS_FILE_LOG_BLOCK_SIZE); 00275 log_block_set_data_len(log_sys->buf, 00276 ut_dulint_minus(recovered_lsn, start_lsn)); 00277 } 00278 00279 if (ut_dulint_cmp(start_lsn, finish_lsn) >= 0) { 00280 00281 return; 00282 } 00283 00284 for (;;) { 00285 end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE); 00286 00287 if (ut_dulint_cmp(end_lsn, finish_lsn) > 0) { 00288 00289 end_lsn = finish_lsn; 00290 } 00291 00292 len = ut_dulint_minus(end_lsn, start_lsn); 00293 00294 log_group_write_buf(group, log_sys->buf, len, start_lsn, 0); 00295 if (ut_dulint_cmp(end_lsn, finish_lsn) >= 0) { 00296 00297 return; 00298 } 00299 00300 /* Write the log buffer full of zeros */ 00301 for (i = 0; i < RECV_SCAN_SIZE; i++) { 00302 00303 *(log_sys->buf + i) = '\0'; 00304 } 00305 00306 start_lsn = end_lsn; 00307 } 00308 }
Here is the call graph for this function:

Here is the caller graph for this function:

page_t* recv_backup_application_page = NULL [static] |
| ibool recv_is_from_backup = FALSE |
| ibool recv_lsn_checks_on = FALSE |
Definition at line 57 of file log0recv.c.
Referenced by buf_page_is_corrupted(), and recv_recovery_from_checkpoint_start().
Definition at line 99 of file log0recv.c.
Referenced by recv_recover_page(), recv_recovery_from_checkpoint_start(), and recv_sys_init().
Definition at line 86 of file log0recv.c.
Referenced by recv_parse_log_rec(), and recv_sys_empty_hash().
| ulint recv_n_pool_free_frames = 256 |
Definition at line 93 of file log0recv.c.
Referenced by buf_read_recv_pages(), log_check_log_recs(), and recv_group_scan_log_recs().
| ibool recv_needed_recovery = FALSE |
Definition at line 55 of file log0recv.c.
Referenced by innobase_start_or_create_for_mysql(), recv_recovery_from_checkpoint_finish(), recv_recovery_from_checkpoint_start(), and recv_scan_log_recs().
| ibool recv_no_ibuf_operations = FALSE |
Definition at line 69 of file log0recv.c.
Referenced by buf_page_io_complete(), fil_io(), ibuf_page(), log_write_up_to(), and recv_apply_hashed_log_recs().
Definition at line 84 of file log0recv.c.
Referenced by recv_parse_log_recs(), and recv_report_corrupt_log().
Definition at line 83 of file log0recv.c.
Referenced by recv_parse_log_recs(), and recv_report_corrupt_log().
| ulint recv_previous_parsed_rec_type = 999999 |
Definition at line 82 of file log0recv.c.
Referenced by recv_parse_log_recs(), and recv_report_corrupt_log().
| ibool recv_recovery_from_backup_on = FALSE |
Definition at line 53 of file log0recv.c.
| ibool recv_recovery_on = FALSE |
Definition at line 52 of file log0recv.c.
Referenced by buf_LRU_buf_pool_running_out(), buf_LRU_get_free_block(), log_preflush_pool_modified_pages(), recv_recovery_from_checkpoint_finish(), and recv_recovery_from_checkpoint_start().
| recv_sys_t* recv_sys = NULL |
Definition at line 51 of file log0recv.c.
Referenced by log_check_log_recs(), log_init(), mlog_parse_nbytes(), mlog_parse_string(), page_cur_parse_insert_rec(), recv_add_to_hash_table(), recv_apply_hashed_log_recs(), recv_apply_log_recs_for_backup(), recv_get_fil_addr_struct(), recv_hash(), recv_parse_log_rec(), recv_parse_log_recs(), recv_parse_or_apply_log_rec_body(), recv_read_in_area(), recv_recover_page(), recv_recovery_from_checkpoint_finish(), recv_recovery_from_checkpoint_start(), recv_report_corrupt_log(), recv_scan_log_recs(), recv_synchronize_groups(), recv_sys_add_to_parsing_buf(), recv_sys_create(), recv_sys_empty_hash(), recv_sys_free(), recv_sys_init(), recv_sys_justify_left_parsing_buf(), and recv_truncate_group().
1.4.7

