00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00033 #include "log0log.h"
00034
00035 #ifdef UNIV_NONINL
00036 #include "log0log.ic"
00037 #endif
00038
00039 #ifndef UNIV_HOTBACKUP
00040 #include "mem0mem.h"
00041 #include "buf0buf.h"
00042 #include "buf0flu.h"
00043 #include "srv0srv.h"
00044 #include "log0recv.h"
00045 #include "fil0fil.h"
00046 #include "dict0boot.h"
00047 #include "srv0srv.h"
00048 #include "srv0start.h"
00049 #include "trx0sys.h"
00050 #include "trx0trx.h"
00051 #include "ha_prototypes.h"
00052
00053 #include <drizzled/errmsg_print.h>
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 UNIV_INTERN ulint log_fsp_current_free_limit = 0;
00084
00085
00086 UNIV_INTERN log_t* log_sys = NULL;
00087
00088 #ifdef UNIV_PFS_RWLOCK
00089 UNIV_INTERN mysql_pfs_key_t checkpoint_lock_key;
00090 # ifdef UNIV_LOG_ARCHIVE
00091 UNIV_INTERN mysql_pfs_key_t archive_lock_key;
00092 # endif
00093 #endif
00094
00095 #ifdef UNIV_PFS_MUTEX
00096 UNIV_INTERN mysql_pfs_key_t log_sys_mutex_key;
00097 UNIV_INTERN mysql_pfs_key_t log_flush_order_mutex_key;
00098 #endif
00099
00100 #ifdef UNIV_DEBUG
00101 UNIV_INTERN ibool log_do_write = TRUE;
00102 #endif
00103
00104
00105
00106 UNIV_INTERN ibool log_has_printed_chkp_warning = FALSE;
00107 UNIV_INTERN time_t log_last_warning_time;
00108
00109 #ifdef UNIV_LOG_ARCHIVE
00110
00111
00112 UNIV_INTERN byte log_archive_io;
00113 #endif
00114
00115
00116 #define LOG_BUF_WRITE_MARGIN (4 * OS_FILE_LOG_BLOCK_SIZE)
00117
00118
00119 #define LOG_BUF_FLUSH_RATIO 2
00120 #define LOG_BUF_FLUSH_MARGIN (LOG_BUF_WRITE_MARGIN + 4 * UNIV_PAGE_SIZE)
00121
00122
00123
00124
00125 #define LOG_CHECKPOINT_FREE_PER_THREAD (4 * UNIV_PAGE_SIZE)
00126 #define LOG_CHECKPOINT_EXTRA_FREE (8 * UNIV_PAGE_SIZE)
00127
00128
00129
00130
00131 #define LOG_POOL_CHECKPOINT_RATIO_ASYNC 32
00132
00133
00134 #define LOG_POOL_PREFLUSH_RATIO_SYNC 16
00135
00136
00137
00138 #define LOG_POOL_PREFLUSH_RATIO_ASYNC 8
00139
00140
00141 #define LOG_ARCHIVE_EXTRA_MARGIN (4 * UNIV_PAGE_SIZE)
00142
00143
00144 #define LOG_ARCHIVE_RATIO_ASYNC 16
00145
00146
00147 #define LOG_UNLOCK_NONE_FLUSHED_LOCK 1
00148 #define LOG_UNLOCK_FLUSH_LOCK 2
00149
00150
00151 #define LOG_ARCHIVE_READ 1
00152 #define LOG_ARCHIVE_WRITE 2
00153
00154
00156 static
00157 void
00158 log_io_complete_checkpoint(void);
00159
00160 #ifdef UNIV_LOG_ARCHIVE
00161
00163 static
00164 void
00165 log_io_complete_archive(void);
00166
00167 #endif
00168
00169
00173 UNIV_INTERN
00174 void
00175 log_fsp_current_free_limit_set_and_checkpoint(
00176
00177 ulint limit)
00178 {
00179 ibool success;
00180
00181 mutex_enter(&(log_sys->mutex));
00182
00183 log_fsp_current_free_limit = limit;
00184
00185 mutex_exit(&(log_sys->mutex));
00186
00187
00188
00189 success = FALSE;
00190
00191 while (!success) {
00192 success = log_checkpoint(TRUE, TRUE);
00193 }
00194 }
00195
00196
00200 static
00201 ib_uint64_t
00202 log_buf_pool_get_oldest_modification(void)
00203
00204 {
00205 ib_uint64_t lsn;
00206
00207 ut_ad(mutex_own(&(log_sys->mutex)));
00208
00209 lsn = buf_pool_get_oldest_modification();
00210
00211 if (!lsn) {
00212
00213 lsn = log_sys->lsn;
00214 }
00215
00216 return(lsn);
00217 }
00218
00219
00223 UNIV_INTERN
00224 ib_uint64_t
00225 log_reserve_and_open(
00226
00227 ulint len)
00228 {
00229 log_t* log = log_sys;
00230 ulint len_upper_limit;
00231 #ifdef UNIV_LOG_ARCHIVE
00232 ulint archived_lsn_age;
00233 ulint dummy;
00234 #endif
00235 #ifdef UNIV_DEBUG
00236 ulint count = 0;
00237 #endif
00238
00239 ut_a(len < log->buf_size / 2);
00240 loop:
00241 mutex_enter(&(log->mutex));
00242 ut_ad(!recv_no_log_write);
00243
00244
00245
00246
00247 len_upper_limit = LOG_BUF_WRITE_MARGIN + (5 * len) / 4;
00248
00249 if (log->buf_free + len_upper_limit > log->buf_size) {
00250
00251 mutex_exit(&(log->mutex));
00252
00253
00254
00255
00256 log_buffer_flush_to_disk();
00257
00258 srv_log_waits++;
00259
00260 ut_ad(++count < 50);
00261
00262 goto loop;
00263 }
00264
00265 #ifdef UNIV_LOG_ARCHIVE
00266 if (log->archiving_state != LOG_ARCH_OFF) {
00267
00268 archived_lsn_age = log->lsn - log->archived_lsn;
00269 if (archived_lsn_age + len_upper_limit
00270 > log->max_archived_lsn_age) {
00271
00272
00273
00274 mutex_exit(&(log->mutex));
00275
00276 ut_ad(len_upper_limit <= log->max_archived_lsn_age);
00277
00278 log_archive_do(TRUE, &dummy);
00279
00280 ut_ad(++count < 50);
00281
00282 goto loop;
00283 }
00284 }
00285 #endif
00286
00287 #ifdef UNIV_LOG_DEBUG
00288 log->old_buf_free = log->buf_free;
00289 log->old_lsn = log->lsn;
00290 #endif
00291 return(log->lsn);
00292 }
00293
00294
00297 UNIV_INTERN
00298 void
00299 log_write_low(
00300
00301 byte* str,
00302 ulint str_len)
00303 {
00304 log_t* log = log_sys;
00305 ulint len;
00306 ulint data_len;
00307 byte* log_block;
00308
00309 ut_ad(mutex_own(&(log->mutex)));
00310 part_loop:
00311 ut_ad(!recv_no_log_write);
00312
00313
00314 data_len = (log->buf_free % OS_FILE_LOG_BLOCK_SIZE) + str_len;
00315
00316 if (data_len <= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
00317
00318
00319
00320 len = str_len;
00321 } else {
00322 data_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE;
00323
00324 len = OS_FILE_LOG_BLOCK_SIZE
00325 - (log->buf_free % OS_FILE_LOG_BLOCK_SIZE)
00326 - LOG_BLOCK_TRL_SIZE;
00327 }
00328
00329 ut_memcpy(log->buf + log->buf_free, str, len);
00330
00331 str_len -= len;
00332 str = str + len;
00333
00334 log_block = static_cast<unsigned char *>(ut_align_down(log->buf + log->buf_free,
00335 OS_FILE_LOG_BLOCK_SIZE));
00336 log_block_set_data_len(log_block, data_len);
00337
00338 if (data_len == OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
00339
00340 log_block_set_data_len(log_block, OS_FILE_LOG_BLOCK_SIZE);
00341 log_block_set_checkpoint_no(log_block,
00342 log_sys->next_checkpoint_no);
00343 len += LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE;
00344
00345 log->lsn += len;
00346
00347
00348 log_block_init(log_block + OS_FILE_LOG_BLOCK_SIZE, log->lsn);
00349 } else {
00350 log->lsn += len;
00351 }
00352
00353 log->buf_free += len;
00354
00355 ut_ad(log->buf_free <= log->buf_size);
00356
00357 if (str_len > 0) {
00358 goto part_loop;
00359 }
00360
00361 srv_log_write_requests++;
00362 }
00363
00364
00366 UNIV_INLINE
00367 ulint
00368 log_max_modified_age_async()
00369
00370 {
00371 if (srv_checkpoint_age_target) {
00372 return(ut_min(log_sys->max_modified_age_async,
00373 srv_checkpoint_age_target
00374 - srv_checkpoint_age_target / 8));
00375 } else {
00376 return(log_sys->max_modified_age_async);
00377 }
00378 }
00379
00380
00382 UNIV_INLINE
00383 ulint
00384 log_max_checkpoint_age_async()
00385
00386 {
00387 if (srv_checkpoint_age_target) {
00388 return(ut_min(log_sys->max_checkpoint_age_async,
00389 srv_checkpoint_age_target));
00390 } else {
00391 return(log_sys->max_checkpoint_age_async);
00392 }
00393 }
00394
00395
00396
00397
00400 UNIV_INTERN
00401 ib_uint64_t
00402 log_close(void)
00403
00404 {
00405 byte* log_block;
00406 ulint first_rec_group;
00407 ib_uint64_t oldest_lsn;
00408 ib_uint64_t lsn;
00409 log_t* log = log_sys;
00410 ib_uint64_t checkpoint_age;
00411
00412 ut_ad(mutex_own(&(log->mutex)));
00413 ut_ad(!recv_no_log_write);
00414
00415 lsn = log->lsn;
00416
00417 log_block = static_cast<unsigned char *>(ut_align_down(log->buf + log->buf_free,
00418 OS_FILE_LOG_BLOCK_SIZE));
00419 first_rec_group = log_block_get_first_rec_group(log_block);
00420
00421 if (first_rec_group == 0) {
00422
00423
00424
00425
00426 log_block_set_first_rec_group(
00427 log_block, log_block_get_data_len(log_block));
00428 }
00429
00430 if (log->buf_free > log->max_buf_free) {
00431
00432 log->check_flush_or_checkpoint = TRUE;
00433 }
00434
00435 checkpoint_age = lsn - log->last_checkpoint_lsn;
00436
00437 if (checkpoint_age >= log->log_group_capacity) {
00438
00439
00440
00441
00442
00443
00444 if (!log_has_printed_chkp_warning
00445 || difftime(time(NULL), log_last_warning_time) > 15) {
00446
00447 log_has_printed_chkp_warning = TRUE;
00448 log_last_warning_time = time(NULL);
00449
00450 ut_print_timestamp(stderr);
00451 fprintf(stderr,
00452 " InnoDB: ERROR: the age of the last"
00453 " checkpoint is %lu,\n"
00454 "InnoDB: which exceeds the log group"
00455 " capacity %lu.\n"
00456 "InnoDB: If you are using big"
00457 " BLOB or TEXT rows, you must set the\n"
00458 "InnoDB: combined size of log files"
00459 " at least 10 times bigger than the\n"
00460 "InnoDB: largest such row.\n",
00461 (ulong) checkpoint_age,
00462 (ulong) log->log_group_capacity);
00463 }
00464 }
00465
00466 if (checkpoint_age <= log_max_modified_age_async()) {
00467
00468 goto function_exit;
00469 }
00470
00471 oldest_lsn = buf_pool_get_oldest_modification();
00472
00473 if (!oldest_lsn
00474 || lsn - oldest_lsn > log_max_modified_age_async()
00475 || checkpoint_age > log_max_checkpoint_age_async()) {
00476
00477 log->check_flush_or_checkpoint = TRUE;
00478 }
00479 function_exit:
00480
00481 #ifdef UNIV_LOG_DEBUG
00482 log_check_log_recs(log->buf + log->old_buf_free,
00483 log->buf_free - log->old_buf_free, log->old_lsn);
00484 #endif
00485
00486 return(lsn);
00487 }
00488
00489 #ifdef UNIV_LOG_ARCHIVE
00490
00493 static
00494 void
00495 log_pad_current_log_block(void)
00496
00497 {
00498 byte b = MLOG_DUMMY_RECORD;
00499 ulint pad_length;
00500 ulint i;
00501 ib_uint64_t lsn;
00502
00503
00504 lsn = log_reserve_and_open(OS_FILE_LOG_BLOCK_SIZE);
00505
00506 pad_length = OS_FILE_LOG_BLOCK_SIZE
00507 - (log_sys->buf_free % OS_FILE_LOG_BLOCK_SIZE)
00508 - LOG_BLOCK_TRL_SIZE;
00509
00510 for (i = 0; i < pad_length; i++) {
00511 log_write_low(&b, 1);
00512 }
00513
00514 lsn = log_sys->lsn;
00515
00516 log_close();
00517 log_release();
00518
00519 ut_a(lsn % OS_FILE_LOG_BLOCK_SIZE == LOG_BLOCK_HDR_SIZE);
00520 }
00521 #endif
00522
00523
00527 UNIV_INTERN
00528 ulint
00529 log_group_get_capacity(
00530
00531 const log_group_t* group)
00532 {
00533 ut_ad(mutex_own(&(log_sys->mutex)));
00534
00535 return((group->file_size - LOG_FILE_HDR_SIZE) * group->n_files);
00536 }
00537
00538
00542 UNIV_INLINE
00543 ulint
00544 log_group_calc_size_offset(
00545
00546 ulint offset,
00548 const log_group_t* group)
00549 {
00550 ut_ad(mutex_own(&(log_sys->mutex)));
00551
00552 return(offset - LOG_FILE_HDR_SIZE * (1 + offset / group->file_size));
00553 }
00554
00555
00559 UNIV_INLINE
00560 ulint
00561 log_group_calc_real_offset(
00562
00563 ulint offset,
00565 const log_group_t* group)
00566 {
00567 ut_ad(mutex_own(&(log_sys->mutex)));
00568
00569 return(offset + LOG_FILE_HDR_SIZE
00570 * (1 + offset / (group->file_size - LOG_FILE_HDR_SIZE)));
00571 }
00572
00573
00576 static
00577 ulint
00578 log_group_calc_lsn_offset(
00579
00580 ib_uint64_t lsn,
00582 const log_group_t* group)
00583 {
00584 ib_uint64_t gr_lsn;
00585 ib_int64_t gr_lsn_size_offset;
00586 ib_int64_t difference;
00587 ib_int64_t group_size;
00588 ib_int64_t offset;
00589
00590 ut_ad(mutex_own(&(log_sys->mutex)));
00591
00592
00593
00594
00595 gr_lsn = group->lsn;
00596
00597 gr_lsn_size_offset = (ib_int64_t)
00598 log_group_calc_size_offset(group->lsn_offset, group);
00599
00600 group_size = (ib_int64_t) log_group_get_capacity(group);
00601
00602 if (lsn >= gr_lsn) {
00603
00604 difference = (ib_int64_t) (lsn - gr_lsn);
00605 } else {
00606 difference = (ib_int64_t) (gr_lsn - lsn);
00607
00608 difference = difference % group_size;
00609
00610 difference = group_size - difference;
00611 }
00612
00613 offset = (gr_lsn_size_offset + difference) % group_size;
00614
00615
00616 ut_a((sizeof(ulint) == 4) || (offset < (((ib_int64_t) 1) << 32)));
00617
00618
00619
00620
00621
00622
00623 return(log_group_calc_real_offset((ulint)offset, group));
00624 }
00625 #endif
00626
00627 #ifdef UNIV_DEBUG
00628 UNIV_INTERN ibool log_debug_writes = FALSE;
00629 #endif
00630
00631
00634 UNIV_INTERN
00635 ulint
00636 log_calc_where_lsn_is(
00637
00638 ib_int64_t* log_file_offset,
00640 ib_uint64_t first_header_lsn,
00642 ib_uint64_t lsn,
00644 ulint n_log_files,
00646 ib_int64_t log_file_size)
00648 {
00649 ib_int64_t capacity = log_file_size - LOG_FILE_HDR_SIZE;
00650 ulint file_no;
00651 ib_int64_t add_this_many;
00652
00653 if (lsn < first_header_lsn) {
00654 add_this_many = 1 + (first_header_lsn - lsn)
00655 / (capacity * (ib_int64_t)n_log_files);
00656 lsn += add_this_many
00657 * capacity * (ib_int64_t)n_log_files;
00658 }
00659
00660 ut_a(lsn >= first_header_lsn);
00661
00662 file_no = ((ulint)((lsn - first_header_lsn) / capacity))
00663 % n_log_files;
00664 *log_file_offset = (lsn - first_header_lsn) % capacity;
00665
00666 *log_file_offset = *log_file_offset + LOG_FILE_HDR_SIZE;
00667
00668 return(file_no);
00669 }
00670
00671 #ifndef UNIV_HOTBACKUP
00672
00676 UNIV_INTERN
00677 void
00678 log_group_set_fields(
00679
00680 log_group_t* group,
00681 ib_uint64_t lsn)
00683 {
00684 group->lsn_offset = log_group_calc_lsn_offset(lsn, group);
00685 group->lsn = lsn;
00686 }
00687
00688
00693 static
00694 ibool
00695 log_calc_max_ages(void)
00696
00697 {
00698 log_group_t* group;
00699 ulint margin;
00700 ulint free;
00701 ibool success = TRUE;
00702 ulint smallest_capacity;
00703 ulint archive_margin;
00704 ulint smallest_archive_margin;
00705
00706 mutex_enter(&(log_sys->mutex));
00707
00708 group = UT_LIST_GET_FIRST(log_sys->log_groups);
00709
00710 ut_ad(group);
00711
00712 smallest_capacity = ULINT_MAX;
00713 smallest_archive_margin = ULINT_MAX;
00714
00715 while (group) {
00716 if (log_group_get_capacity(group) < smallest_capacity) {
00717
00718 smallest_capacity = log_group_get_capacity(group);
00719 }
00720
00721 archive_margin = log_group_get_capacity(group)
00722 - (group->file_size - LOG_FILE_HDR_SIZE)
00723 - LOG_ARCHIVE_EXTRA_MARGIN;
00724
00725 if (archive_margin < smallest_archive_margin) {
00726
00727 smallest_archive_margin = archive_margin;
00728 }
00729
00730 group = UT_LIST_GET_NEXT(log_groups, group);
00731 }
00732
00733
00734 smallest_capacity = smallest_capacity - smallest_capacity / 10;
00735
00736
00737
00738
00739
00740
00741 free = LOG_CHECKPOINT_FREE_PER_THREAD * (10 + srv_thread_concurrency)
00742 + LOG_CHECKPOINT_EXTRA_FREE;
00743 if (free >= smallest_capacity / 2) {
00744 success = FALSE;
00745
00746 goto failure;
00747 } else {
00748 margin = smallest_capacity - free;
00749 }
00750
00751 margin = ut_min(margin, log_sys->adm_checkpoint_interval);
00752
00753 margin = margin - margin / 10;
00754
00755 log_sys->log_group_capacity = smallest_capacity;
00756
00757 log_sys->max_modified_age_async = margin
00758 - margin / LOG_POOL_PREFLUSH_RATIO_ASYNC;
00759 log_sys->max_modified_age_sync = margin
00760 - margin / LOG_POOL_PREFLUSH_RATIO_SYNC;
00761
00762 log_sys->max_checkpoint_age_async = margin - margin
00763 / LOG_POOL_CHECKPOINT_RATIO_ASYNC;
00764 log_sys->max_checkpoint_age = margin;
00765
00766 #ifdef UNIV_LOG_ARCHIVE
00767 log_sys->max_archived_lsn_age = smallest_archive_margin;
00768
00769 log_sys->max_archived_lsn_age_async = smallest_archive_margin
00770 - smallest_archive_margin / LOG_ARCHIVE_RATIO_ASYNC;
00771 #endif
00772 failure:
00773 mutex_exit(&(log_sys->mutex));
00774
00775 if (!success) {
00776 fprintf(stderr,
00777 "InnoDB: Error: ib_logfiles are too small"
00778 " for innodb_thread_concurrency %lu.\n"
00779 "InnoDB: The combined size of ib_logfiles"
00780 " should be bigger than\n"
00781 "InnoDB: 200 kB * innodb_thread_concurrency.\n"
00782 "InnoDB: To get mysqld to start up, set"
00783 " innodb_thread_concurrency in my.cnf\n"
00784 "InnoDB: to a lower value, for example, to 8."
00785 " After an ERROR-FREE shutdown\n"
00786 "InnoDB: of mysqld you can adjust the size of"
00787 " ib_logfiles, as explained in\n"
00788 "InnoDB: " REFMAN "adding-and-removing.html\n"
00789 "InnoDB: Cannot continue operation."
00790 " Calling exit(1).\n",
00791 (ulong)srv_thread_concurrency);
00792
00793 exit(1);
00794 }
00795
00796 return(success);
00797 }
00798
00799
00801 UNIV_INTERN
00802 void
00803 log_init(void)
00804
00805 {
00806 log_sys = static_cast<log_t *>(mem_alloc(sizeof(log_t)));
00807
00808 mutex_create(log_sys_mutex_key, &log_sys->mutex, SYNC_LOG);
00809
00810 mutex_create(log_flush_order_mutex_key,
00811 &log_sys->log_flush_order_mutex,
00812 SYNC_LOG_FLUSH_ORDER);
00813
00814 mutex_enter(&(log_sys->mutex));
00815
00816
00817
00818
00819 log_sys->lsn = LOG_START_LSN;
00820
00821 ut_a(LOG_BUFFER_SIZE >= 16 * OS_FILE_LOG_BLOCK_SIZE);
00822 ut_a(LOG_BUFFER_SIZE >= 4 * UNIV_PAGE_SIZE);
00823
00824 log_sys->buf_ptr = static_cast<unsigned char *>(mem_alloc(LOG_BUFFER_SIZE + OS_FILE_LOG_BLOCK_SIZE));
00825 log_sys->buf = static_cast<unsigned char *>(ut_align(log_sys->buf_ptr, OS_FILE_LOG_BLOCK_SIZE));
00826
00827 log_sys->buf_size = LOG_BUFFER_SIZE;
00828
00829 memset(log_sys->buf, '\0', LOG_BUFFER_SIZE);
00830
00831 log_sys->max_buf_free = log_sys->buf_size / LOG_BUF_FLUSH_RATIO
00832 - LOG_BUF_FLUSH_MARGIN;
00833 log_sys->check_flush_or_checkpoint = TRUE;
00834 UT_LIST_INIT(log_sys->log_groups);
00835
00836 log_sys->n_log_ios = 0;
00837
00838 log_sys->n_log_ios_old = log_sys->n_log_ios;
00839 log_sys->last_printout_time = time(NULL);
00840
00841
00842 log_sys->buf_next_to_write = 0;
00843
00844 log_sys->write_lsn = 0;
00845 log_sys->current_flush_lsn = 0;
00846 log_sys->flushed_to_disk_lsn = 0;
00847
00848 log_sys->written_to_some_lsn = log_sys->lsn;
00849 log_sys->written_to_all_lsn = log_sys->lsn;
00850
00851 log_sys->n_pending_writes = 0;
00852
00853 log_sys->no_flush_event = os_event_create(NULL);
00854
00855 os_event_set(log_sys->no_flush_event);
00856
00857 log_sys->one_flushed_event = os_event_create(NULL);
00858
00859 os_event_set(log_sys->one_flushed_event);
00860
00861
00862 log_sys->adm_checkpoint_interval = ULINT_MAX;
00863
00864 log_sys->next_checkpoint_no = 0;
00865 log_sys->last_checkpoint_lsn = log_sys->lsn;
00866 log_sys->n_pending_checkpoint_writes = 0;
00867
00868 rw_lock_create(checkpoint_lock_key, &log_sys->checkpoint_lock,
00869 SYNC_NO_ORDER_CHECK);
00870
00871 log_sys->checkpoint_buf_ptr = static_cast<unsigned char *>(mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE));
00872 log_sys->checkpoint_buf = static_cast<unsigned char *>(ut_align(log_sys->checkpoint_buf_ptr,
00873 OS_FILE_LOG_BLOCK_SIZE));
00874 memset(log_sys->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE);
00875
00876
00877 #ifdef UNIV_LOG_ARCHIVE
00878
00879 log_sys->archiving_state = LOG_ARCH_OFF;
00880 log_sys->archived_lsn = log_sys->lsn;
00881 log_sys->next_archived_lsn = 0;
00882
00883 log_sys->n_pending_archive_ios = 0;
00884
00885 rw_lock_create(archive_lock_key, &log_sys->archive_lock,
00886 SYNC_NO_ORDER_CHECK);
00887
00888 log_sys->archive_buf = NULL;
00889
00890
00891
00892
00893
00894 log_sys->archive_buf_size = 0;
00895
00896
00897
00898 log_sys->archiving_on = os_event_create(NULL);
00899 #endif
00900
00901
00902
00903 log_block_init(log_sys->buf, log_sys->lsn);
00904 log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE);
00905
00906 log_sys->buf_free = LOG_BLOCK_HDR_SIZE;
00907 log_sys->lsn = LOG_START_LSN + LOG_BLOCK_HDR_SIZE;
00908
00909 mutex_exit(&(log_sys->mutex));
00910
00911 #ifdef UNIV_LOG_DEBUG
00912 recv_sys_create();
00913 recv_sys_init(buf_pool_get_curr_size());
00914
00915 recv_sys->parse_start_lsn = log_sys->lsn;
00916 recv_sys->scanned_lsn = log_sys->lsn;
00917 recv_sys->scanned_checkpoint_no = 0;
00918 recv_sys->recovered_lsn = log_sys->lsn;
00919 recv_sys->limit_lsn = IB_ULONGLONG_MAX;
00920 #endif
00921 }
00922
00923
00925 UNIV_INTERN
00926 void
00927 log_group_init(
00928
00929 ulint id,
00930 ulint n_files,
00931 ulint file_size,
00932 ulint space_id,
00935 ulint )
00941 {
00942 ulint i;
00943
00944 log_group_t* group;
00945
00946 group = static_cast<log_group_t *>(mem_alloc(sizeof(log_group_t)));
00947
00948 group->id = id;
00949 group->n_files = n_files;
00950 group->file_size = file_size;
00951 group->space_id = space_id;
00952 group->state = LOG_GROUP_OK;
00953 group->lsn = LOG_START_LSN;
00954 group->lsn_offset = LOG_FILE_HDR_SIZE;
00955 group->n_pending_writes = 0;
00956
00957 group->file_header_bufs_ptr = static_cast<unsigned char **>(mem_alloc(sizeof(byte*) * n_files));
00958 group->file_header_bufs = static_cast<unsigned char **>(mem_alloc(sizeof(byte*) * n_files));
00959 #ifdef UNIV_LOG_ARCHIVE
00960 group->archive_file_header_bufs_ptr = mem_alloc(
00961 sizeof(byte*) * n_files);
00962 group->archive_file_header_bufs = mem_alloc(sizeof(byte*) * n_files);
00963 #endif
00964
00965 for (i = 0; i < n_files; i++) {
00966 group->file_header_bufs_ptr[i] = static_cast<unsigned char *>(mem_alloc(
00967 LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE));
00968
00969 group->file_header_bufs[i] = static_cast<unsigned char *>(ut_align(
00970 group->file_header_bufs_ptr[i],
00971 OS_FILE_LOG_BLOCK_SIZE));
00972
00973 memset(*(group->file_header_bufs + i), '\0',
00974 LOG_FILE_HDR_SIZE);
00975
00976 #ifdef UNIV_LOG_ARCHIVE
00977 group->archive_file_header_bufs_ptr[i] = mem_alloc(
00978 LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
00979
00980 group->archive_file_header_bufs[i] = ut_align(
00981 group->archive_file_header_bufs_ptr[i],
00982 OS_FILE_LOG_BLOCK_SIZE);
00983
00984 memset(*(group->archive_file_header_bufs + i), '\0',
00985 LOG_FILE_HDR_SIZE);
00986 #endif
00987 }
00988
00989 #ifdef UNIV_LOG_ARCHIVE
00990 group->archive_space_id = archive_space_id;
00991
00992 group->archived_file_no = 0;
00993 group->archived_offset = 0;
00994 #endif
00995
00996 group->checkpoint_buf_ptr = static_cast<unsigned char *>(mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE));
00997 group->checkpoint_buf = static_cast<unsigned char*>(ut_align(group->checkpoint_buf_ptr,
00998 OS_FILE_LOG_BLOCK_SIZE));
00999
01000 memset(group->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE);
01001
01002 UT_LIST_ADD_LAST(log_groups, log_sys->log_groups, group);
01003
01004 ut_a(log_calc_max_ages());
01005 }
01006
01007
01009 UNIV_INLINE
01010 void
01011 log_flush_do_unlocks(
01012
01013 ulint code)
01015 {
01016 ut_ad(mutex_own(&(log_sys->mutex)));
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029 if (code & LOG_UNLOCK_NONE_FLUSHED_LOCK) {
01030 os_event_set(log_sys->one_flushed_event);
01031 }
01032
01033 if (code & LOG_UNLOCK_FLUSH_LOCK) {
01034 os_event_set(log_sys->no_flush_event);
01035 }
01036 }
01037
01038
01042 UNIV_INLINE
01043 ulint
01044 log_group_check_flush_completion(
01045
01046 log_group_t* group)
01047 {
01048 ut_ad(mutex_own(&(log_sys->mutex)));
01049
01050 if (!log_sys->one_flushed && group->n_pending_writes == 0) {
01051 #ifdef UNIV_DEBUG
01052 if (log_debug_writes) {
01053 fprintf(stderr,
01054 "Log flushed first to group %lu\n",
01055 (ulong) group->id);
01056 }
01057 #endif
01058 log_sys->written_to_some_lsn = log_sys->write_lsn;
01059 log_sys->one_flushed = TRUE;
01060
01061 return(LOG_UNLOCK_NONE_FLUSHED_LOCK);
01062 }
01063
01064 #ifdef UNIV_DEBUG
01065 if (log_debug_writes && (group->n_pending_writes == 0)) {
01066
01067 fprintf(stderr, "Log flushed to group %lu\n",
01068 (ulong) group->id);
01069 }
01070 #endif
01071 return(0);
01072 }
01073
01074
01077 static
01078 ulint
01079 log_sys_check_flush_completion(void)
01080
01081 {
01082 ulint move_start;
01083 ulint move_end;
01084
01085 ut_ad(mutex_own(&(log_sys->mutex)));
01086
01087 if (log_sys->n_pending_writes == 0) {
01088
01089 log_sys->written_to_all_lsn = log_sys->write_lsn;
01090 log_sys->buf_next_to_write = log_sys->write_end_offset;
01091
01092 if (log_sys->write_end_offset > log_sys->max_buf_free / 2) {
01093
01094
01095
01096 move_start = ut_calc_align_down(
01097 log_sys->write_end_offset,
01098 OS_FILE_LOG_BLOCK_SIZE);
01099 move_end = ut_calc_align(log_sys->buf_free,
01100 OS_FILE_LOG_BLOCK_SIZE);
01101
01102 ut_memmove(log_sys->buf, log_sys->buf + move_start,
01103 move_end - move_start);
01104 log_sys->buf_free -= move_start;
01105
01106 log_sys->buf_next_to_write -= move_start;
01107 }
01108
01109 return(LOG_UNLOCK_FLUSH_LOCK);
01110 }
01111
01112 return(0);
01113 }
01114
01115
01117 UNIV_INTERN
01118 void
01119 log_io_complete(
01120
01121 log_group_t* group)
01122 {
01123 ulint unlock;
01124
01125 #ifdef UNIV_LOG_ARCHIVE
01126 if ((byte*)group == &log_archive_io) {
01127
01128
01129 log_io_complete_archive();
01130
01131 return;
01132 }
01133 #endif
01134
01135 if ((ulint)group & 0x1UL) {
01136
01137 group = (log_group_t*)((ulint)group - 1);
01138
01139 if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC
01140 && srv_unix_file_flush_method != SRV_UNIX_ALL_O_DIRECT
01141 && srv_unix_file_flush_method != SRV_UNIX_NOSYNC) {
01142
01143 fil_flush(group->space_id);
01144 }
01145
01146 #ifdef UNIV_DEBUG
01147 if (log_debug_writes) {
01148 fprintf(stderr,
01149 "Checkpoint info written to group %lu\n",
01150 group->id);
01151 }
01152 #endif
01153 log_io_complete_checkpoint();
01154
01155 return;
01156 }
01157
01158 ut_error;
01161 if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC
01162 && srv_unix_file_flush_method != SRV_UNIX_ALL_O_DIRECT
01163 && srv_unix_file_flush_method != SRV_UNIX_NOSYNC
01164 && srv_flush_log_at_trx_commit != 2) {
01165
01166 fil_flush(group->space_id);
01167 }
01168
01169 mutex_enter(&(log_sys->mutex));
01170 ut_ad(!recv_no_log_write);
01171
01172 ut_a(group->n_pending_writes > 0);
01173 ut_a(log_sys->n_pending_writes > 0);
01174
01175 group->n_pending_writes--;
01176 log_sys->n_pending_writes--;
01177
01178 unlock = log_group_check_flush_completion(group);
01179 unlock = unlock | log_sys_check_flush_completion();
01180
01181 log_flush_do_unlocks(unlock);
01182
01183 mutex_exit(&(log_sys->mutex));
01184 }
01185
01186
01188 static
01189 void
01190 log_group_file_header_flush(
01191
01192 log_group_t* group,
01193 ulint nth_file,
01195 ib_uint64_t start_lsn)
01197 {
01198 byte* buf;
01199 ulint dest_offset;
01200
01201 ut_ad(mutex_own(&(log_sys->mutex)));
01202 ut_ad(!recv_no_log_write);
01203 ut_a(nth_file < group->n_files);
01204
01205 buf = *(group->file_header_bufs + nth_file);
01206
01207 mach_write_to_4(buf + LOG_GROUP_ID, group->id);
01208 mach_write_to_8(buf + LOG_FILE_START_LSN, start_lsn);
01209
01210
01211 memcpy(buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, " ", 4);
01212
01213 mach_write_to_4(buf + LOG_FILE_OS_FILE_LOG_BLOCK_SIZE,
01214 srv_log_block_size);
01215
01216 dest_offset = nth_file * group->file_size;
01217
01218 #ifdef UNIV_DEBUG
01219 if (log_debug_writes) {
01220 fprintf(stderr,
01221 "Writing log file header to group %lu file %lu\n",
01222 (ulong) group->id, (ulong) nth_file);
01223 }
01224 #endif
01225 if (log_do_write) {
01226 log_sys->n_log_ios++;
01227
01228 srv_os_log_pending_writes++;
01229
01230 fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id, 0,
01231 dest_offset / UNIV_PAGE_SIZE,
01232 dest_offset % UNIV_PAGE_SIZE,
01233 OS_FILE_LOG_BLOCK_SIZE,
01234 buf, group);
01235
01236 srv_os_log_pending_writes--;
01237 }
01238 }
01239
01240
01244 static
01245 void
01246 log_block_store_checksum(
01247
01248 byte* block)
01249 {
01250 log_block_set_checksum(block, log_block_calc_checksum(block));
01251 }
01252
01253
01255 UNIV_INTERN
01256 void
01257 log_group_write_buf(
01258
01259 log_group_t* group,
01260 byte* buf,
01261 ulint len,
01263 ib_uint64_t start_lsn,
01266 ulint new_data_offset)
01270 {
01271 ulint write_len;
01272 ibool write_header;
01273 ulint next_offset;
01274 ulint i;
01275
01276 ut_ad(mutex_own(&(log_sys->mutex)));
01277 ut_ad(!recv_no_log_write);
01278 ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0);
01279 ut_a(((ulint) start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
01280
01281 if (new_data_offset == 0) {
01282 write_header = TRUE;
01283 } else {
01284 write_header = FALSE;
01285 }
01286 loop:
01287 if (len == 0) {
01288
01289 return;
01290 }
01291
01292 next_offset = log_group_calc_lsn_offset(start_lsn, group);
01293
01294 if ((next_offset % group->file_size == LOG_FILE_HDR_SIZE)
01295 && write_header) {
01296
01297
01298 log_group_file_header_flush(group,
01299 next_offset / group->file_size,
01300 start_lsn);
01301 srv_os_log_written+= OS_FILE_LOG_BLOCK_SIZE;
01302 srv_log_writes++;
01303 }
01304
01305 if ((next_offset % group->file_size) + len > group->file_size) {
01306
01307 write_len = group->file_size
01308 - (next_offset % group->file_size);
01309 } else {
01310 write_len = len;
01311 }
01312
01313 #ifdef UNIV_DEBUG
01314 if (log_debug_writes) {
01315
01316 fprintf(stderr,
01317 "Writing log file segment to group %lu"
01318 " offset %lu len %lu\n"
01319 "start lsn %"PRIu64"\n"
01320 "First block n:o %lu last block n:o %lu\n",
01321 (ulong) group->id, (ulong) next_offset,
01322 (ulong) write_len,
01323 start_lsn,
01324 (ulong) log_block_get_hdr_no(buf),
01325 (ulong) log_block_get_hdr_no(
01326 buf + write_len - OS_FILE_LOG_BLOCK_SIZE));
01327 ut_a(log_block_get_hdr_no(buf)
01328 == log_block_convert_lsn_to_no(start_lsn));
01329
01330 for (i = 0; i < write_len / OS_FILE_LOG_BLOCK_SIZE; i++) {
01331
01332 ut_a(log_block_get_hdr_no(buf) + i
01333 == log_block_get_hdr_no(
01334 buf + i * OS_FILE_LOG_BLOCK_SIZE));
01335 }
01336 }
01337 #endif
01338
01339
01340
01341 for (i = 0; i < write_len / OS_FILE_LOG_BLOCK_SIZE; i++) {
01342 log_block_store_checksum(buf + i * OS_FILE_LOG_BLOCK_SIZE);
01343 }
01344
01345 if (log_do_write) {
01346 log_sys->n_log_ios++;
01347
01348 srv_os_log_pending_writes++;
01349
01350 fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id, 0,
01351 next_offset / UNIV_PAGE_SIZE,
01352 next_offset % UNIV_PAGE_SIZE, write_len, buf, group);
01353
01354 srv_os_log_pending_writes--;
01355
01356 srv_os_log_written+= write_len;
01357 srv_log_writes++;
01358 }
01359
01360 if (write_len < len) {
01361 start_lsn += write_len;
01362 len -= write_len;
01363 buf += write_len;
01364
01365 write_header = TRUE;
01366
01367 goto loop;
01368 }
01369 }
01370
01371
01376 UNIV_INTERN
01377 void
01378 log_write_up_to(
01379
01380 ib_uint64_t lsn,
01383 ulint wait,
01385 ibool flush_to_disk)
01388 {
01389 log_group_t* group;
01390 ulint start_offset;
01391 ulint end_offset;
01392 ulint area_start;
01393 ulint area_end;
01394 #ifdef UNIV_DEBUG
01395 ulint loop_count = 0;
01396 #endif
01397 ulint unlock;
01398
01399 if (recv_no_ibuf_operations || srv_fake_write) {
01400
01401
01402
01403 return;
01404 }
01405
01406 loop:
01407 #ifdef UNIV_DEBUG
01408 loop_count++;
01409
01410 ut_ad(loop_count < 5);
01411
01412 # if 0
01413 if (loop_count > 2) {
01414 fprintf(stderr, "Log loop count %lu\n", loop_count);
01415 }
01416 # endif
01417 #endif
01418
01419 mutex_enter(&(log_sys->mutex));
01420 ut_ad(!recv_no_log_write);
01421
01422 if (flush_to_disk
01423 && log_sys->flushed_to_disk_lsn >= lsn) {
01424
01425 mutex_exit(&(log_sys->mutex));
01426
01427 return;
01428 }
01429
01430 if (!flush_to_disk
01431 && (log_sys->written_to_all_lsn >= lsn
01432 || (log_sys->written_to_some_lsn >= lsn
01433 && wait != LOG_WAIT_ALL_GROUPS))) {
01434
01435 mutex_exit(&(log_sys->mutex));
01436
01437 return;
01438 }
01439
01440 if (log_sys->n_pending_writes > 0) {
01441
01442
01443 if (flush_to_disk
01444 && log_sys->current_flush_lsn >= lsn) {
01445
01446
01447
01448 goto do_waits;
01449 }
01450
01451 if (!flush_to_disk
01452 && log_sys->write_lsn >= lsn) {
01453
01454
01455
01456 goto do_waits;
01457 }
01458
01459 mutex_exit(&(log_sys->mutex));
01460
01461
01462
01463
01464 os_event_wait(log_sys->no_flush_event);
01465
01466 goto loop;
01467 }
01468
01469 if (!flush_to_disk
01470 && log_sys->buf_free == log_sys->buf_next_to_write) {
01471
01472
01473 mutex_exit(&(log_sys->mutex));
01474
01475 return;
01476 }
01477
01478 #ifdef UNIV_DEBUG
01479 if (log_debug_writes) {
01480 fprintf(stderr,
01481 "Writing log from %"PRIu64" up to lsn %"PRIu64"\n",
01482 log_sys->written_to_all_lsn,
01483 log_sys->lsn);
01484 }
01485 #endif
01486 log_sys->n_pending_writes++;
01487
01488 group = UT_LIST_GET_FIRST(log_sys->log_groups);
01489 group->n_pending_writes++;
01492 os_event_reset(log_sys->no_flush_event);
01493 os_event_reset(log_sys->one_flushed_event);
01494
01495 start_offset = log_sys->buf_next_to_write;
01496 end_offset = log_sys->buf_free;
01497
01498 area_start = ut_calc_align_down(start_offset, OS_FILE_LOG_BLOCK_SIZE);
01499 area_end = ut_calc_align(end_offset, OS_FILE_LOG_BLOCK_SIZE);
01500
01501 ut_ad(area_end - area_start > 0);
01502
01503 log_sys->write_lsn = log_sys->lsn;
01504
01505 if (flush_to_disk) {
01506 log_sys->current_flush_lsn = log_sys->lsn;
01507 }
01508
01509 log_sys->one_flushed = FALSE;
01510
01511 log_block_set_flush_bit(log_sys->buf + area_start, TRUE);
01512 log_block_set_checkpoint_no(
01513 log_sys->buf + area_end - OS_FILE_LOG_BLOCK_SIZE,
01514 log_sys->next_checkpoint_no);
01515
01516
01517
01518
01519
01520 ut_memcpy(log_sys->buf + area_end,
01521 log_sys->buf + area_end - OS_FILE_LOG_BLOCK_SIZE,
01522 OS_FILE_LOG_BLOCK_SIZE);
01523
01524 log_sys->buf_free += OS_FILE_LOG_BLOCK_SIZE;
01525 log_sys->write_end_offset = log_sys->buf_free;
01526
01527 group = UT_LIST_GET_FIRST(log_sys->log_groups);
01528
01529
01530
01531 while (group) {
01532 log_group_write_buf(
01533 group, log_sys->buf + area_start,
01534 area_end - area_start,
01535 ut_uint64_align_down(log_sys->written_to_all_lsn,
01536 OS_FILE_LOG_BLOCK_SIZE),
01537 start_offset - area_start);
01538
01539 log_group_set_fields(group, log_sys->write_lsn);
01540
01541 group = UT_LIST_GET_NEXT(log_groups, group);
01542 }
01543
01544 mutex_exit(&(log_sys->mutex));
01545
01546 if (srv_unix_file_flush_method == SRV_UNIX_O_DSYNC
01547 || srv_unix_file_flush_method == SRV_UNIX_ALL_O_DIRECT) {
01548
01549
01550
01551 log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
01552
01553 } else if (flush_to_disk) {
01554
01555 group = UT_LIST_GET_FIRST(log_sys->log_groups);
01556
01557 fil_flush(group->space_id);
01558 log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
01559 }
01560
01561 mutex_enter(&(log_sys->mutex));
01562
01563 group = UT_LIST_GET_FIRST(log_sys->log_groups);
01564
01565 ut_a(group->n_pending_writes == 1);
01566 ut_a(log_sys->n_pending_writes == 1);
01567
01568 group->n_pending_writes--;
01569 log_sys->n_pending_writes--;
01570
01571 unlock = log_group_check_flush_completion(group);
01572 unlock = unlock | log_sys_check_flush_completion();
01573
01574 log_flush_do_unlocks(unlock);
01575
01576 mutex_exit(&(log_sys->mutex));
01577
01578 return;
01579
01580 do_waits:
01581 mutex_exit(&(log_sys->mutex));
01582
01583 switch (wait) {
01584 case LOG_WAIT_ONE_GROUP:
01585 os_event_wait(log_sys->one_flushed_event);
01586 break;
01587 case LOG_WAIT_ALL_GROUPS:
01588 os_event_wait(log_sys->no_flush_event);
01589 break;
01590 #ifdef UNIV_DEBUG
01591 case LOG_NO_WAIT:
01592 break;
01593 default:
01594 ut_error;
01595 #endif
01596 }
01597 }
01598
01599
01601 UNIV_INTERN
01602 void
01603 log_buffer_flush_to_disk(void)
01604
01605 {
01606 ib_uint64_t lsn;
01607
01608 mutex_enter(&(log_sys->mutex));
01609
01610 lsn = log_sys->lsn;
01611
01612 mutex_exit(&(log_sys->mutex));
01613
01614 log_write_up_to(lsn, LOG_WAIT_ALL_GROUPS, TRUE);
01615 }
01616
01617
01622 UNIV_INTERN
01623 void
01624 log_buffer_sync_in_background(
01625
01626 ibool flush)
01627 {
01628 ib_uint64_t lsn;
01629
01630 mutex_enter(&(log_sys->mutex));
01631
01632 lsn = log_sys->lsn;
01633
01634 mutex_exit(&(log_sys->mutex));
01635
01636 log_write_up_to(lsn, LOG_NO_WAIT, flush);
01637 }
01638
01639
01640
01641
01642
01643 static
01644 void
01645 log_flush_margin(void)
01646
01647 {
01648 log_t* log = log_sys;
01649 ib_uint64_t lsn = 0;
01650
01651 mutex_enter(&(log->mutex));
01652
01653 if (log->buf_free > log->max_buf_free) {
01654
01655 if (log->n_pending_writes > 0) {
01656
01657
01658 } else {
01659 lsn = log->lsn;
01660 }
01661 }
01662
01663 mutex_exit(&(log->mutex));
01664
01665 if (lsn) {
01666 log_write_up_to(lsn, LOG_NO_WAIT, FALSE);
01667 }
01668 }
01669
01670
01676 UNIV_INTERN
01677 ibool
01678 log_preflush_pool_modified_pages(
01679
01680 ib_uint64_t new_oldest,
01683 ibool sync)
01685 {
01686 ulint n_pages;
01687
01688 if (recv_recovery_on) {
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698 recv_apply_hashed_log_recs(TRUE);
01699 }
01700
01701 n_pages = buf_flush_list(ULINT_MAX, new_oldest);
01702
01703 if (sync) {
01704 buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
01705 }
01706
01707 if (n_pages == ULINT_UNDEFINED) {
01708
01709 return(FALSE);
01710 }
01711
01712 return(TRUE);
01713 }
01714
01715
01717 static
01718 void
01719 log_complete_checkpoint(void)
01720
01721 {
01722 ut_ad(mutex_own(&(log_sys->mutex)));
01723 ut_ad(log_sys->n_pending_checkpoint_writes == 0);
01724
01725 log_sys->next_checkpoint_no++;
01726
01727 log_sys->last_checkpoint_lsn = log_sys->next_checkpoint_lsn;
01728
01729 rw_lock_x_unlock_gen(&(log_sys->checkpoint_lock), LOG_CHECKPOINT);
01730 }
01731
01732
01734 static
01735 void
01736 log_io_complete_checkpoint(void)
01737
01738 {
01739 mutex_enter(&(log_sys->mutex));
01740
01741 ut_ad(log_sys->n_pending_checkpoint_writes > 0);
01742
01743 log_sys->n_pending_checkpoint_writes--;
01744
01745 if (log_sys->n_pending_checkpoint_writes == 0) {
01746 log_complete_checkpoint();
01747 }
01748
01749 mutex_exit(&(log_sys->mutex));
01750 }
01751
01752
01754 static
01755 void
01756 log_checkpoint_set_nth_group_info(
01757
01758 byte* buf,
01759 ulint n,
01760 ulint file_no,
01761 ulint offset)
01762 {
01763 ut_ad(n < LOG_MAX_N_GROUPS);
01764
01765 mach_write_to_4(buf + LOG_CHECKPOINT_GROUP_ARRAY
01766 + 8 * n + LOG_CHECKPOINT_ARCHIVED_FILE_NO, file_no);
01767 mach_write_to_4(buf + LOG_CHECKPOINT_GROUP_ARRAY
01768 + 8 * n + LOG_CHECKPOINT_ARCHIVED_OFFSET, offset);
01769 }
01770
01771
01773 UNIV_INTERN
01774 void
01775 log_checkpoint_get_nth_group_info(
01776
01777 const byte* buf,
01778 ulint n,
01779 ulint* file_no,
01780 ulint* offset)
01781 {
01782 ut_ad(n < LOG_MAX_N_GROUPS);
01783
01784 *file_no = mach_read_from_4(buf + LOG_CHECKPOINT_GROUP_ARRAY
01785 + 8 * n + LOG_CHECKPOINT_ARCHIVED_FILE_NO);
01786 *offset = mach_read_from_4(buf + LOG_CHECKPOINT_GROUP_ARRAY
01787 + 8 * n + LOG_CHECKPOINT_ARCHIVED_OFFSET);
01788 }
01789
01790
01792 static
01793 void
01794 log_group_checkpoint(
01795
01796 log_group_t* group)
01797 {
01798 log_group_t* group2;
01799 #ifdef UNIV_LOG_ARCHIVE
01800 ib_uint64_t archived_lsn;
01801 ib_uint64_t next_archived_lsn;
01802 #endif
01803 ulint write_offset;
01804 ulint fold;
01805 byte* buf;
01806 ulint i;
01807
01808 ut_ad(mutex_own(&(log_sys->mutex)));
01809 ut_a(LOG_CHECKPOINT_SIZE <= OS_FILE_LOG_BLOCK_SIZE);
01810
01811 buf = group->checkpoint_buf;
01812
01813 mach_write_to_8(buf + LOG_CHECKPOINT_NO, log_sys->next_checkpoint_no);
01814 mach_write_to_8(buf + LOG_CHECKPOINT_LSN, log_sys->next_checkpoint_lsn);
01815
01816 mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET,
01817 log_group_calc_lsn_offset(
01818 log_sys->next_checkpoint_lsn, group));
01819
01820 mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, log_sys->buf_size);
01821
01822 #ifdef UNIV_LOG_ARCHIVE
01823 if (log_sys->archiving_state == LOG_ARCH_OFF) {
01824 archived_lsn = IB_ULONGLONG_MAX;
01825 } else {
01826 archived_lsn = log_sys->archived_lsn;
01827
01828 if (archived_lsn != log_sys->next_archived_lsn) {
01829 next_archived_lsn = log_sys->next_archived_lsn;
01830
01831 }
01832 }
01833
01834 mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, archived_lsn);
01835 #else
01836 mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN,
01837 (ib_uint64_t)log_group_calc_lsn_offset(
01838 log_sys->next_checkpoint_lsn, group));
01839
01840 #endif
01841
01842 for (i = 0; i < LOG_MAX_N_GROUPS; i++) {
01843 log_checkpoint_set_nth_group_info(buf, i, 0, 0);
01844 }
01845
01846 group2 = UT_LIST_GET_FIRST(log_sys->log_groups);
01847
01848 while (group2) {
01849 log_checkpoint_set_nth_group_info(buf, group2->id,
01850 #ifdef UNIV_LOG_ARCHIVE
01851 group2->archived_file_no,
01852 group2->archived_offset
01853 #else
01854 0, 0
01855 #endif
01856 );
01857
01858 group2 = UT_LIST_GET_NEXT(log_groups, group2);
01859 }
01860
01861 fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1);
01862 mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_1, fold);
01863
01864 fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
01865 LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
01866 mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_2, fold);
01867
01868
01869
01870
01871 mach_write_to_4(buf + LOG_CHECKPOINT_FSP_FREE_LIMIT,
01872 log_fsp_current_free_limit);
01873
01874 mach_write_to_4(buf + LOG_CHECKPOINT_FSP_MAGIC_N,
01875 LOG_CHECKPOINT_FSP_MAGIC_N_VAL);
01876
01877
01878
01879
01880 if ((log_sys->next_checkpoint_no & 1) == 0) {
01881 write_offset = LOG_CHECKPOINT_1;
01882 } else {
01883 write_offset = LOG_CHECKPOINT_2;
01884 }
01885
01886 if (log_do_write) {
01887 if (log_sys->n_pending_checkpoint_writes == 0) {
01888
01889 rw_lock_x_lock_gen(&(log_sys->checkpoint_lock),
01890 LOG_CHECKPOINT);
01891 }
01892
01893 log_sys->n_pending_checkpoint_writes++;
01894
01895 log_sys->n_log_ios++;
01896
01897
01898
01899
01900
01901 fil_io(OS_FILE_WRITE | OS_FILE_LOG, FALSE, group->space_id, 0,
01902 write_offset / UNIV_PAGE_SIZE,
01903 write_offset % UNIV_PAGE_SIZE,
01904 OS_FILE_LOG_BLOCK_SIZE,
01905 buf, ((byte*)group + 1));
01906
01907 ut_ad(((ulint)group & 0x1UL) == 0);
01908 }
01909 }
01910 #endif
01911
01912 #ifdef UNIV_HOTBACKUP
01913
01916 UNIV_INTERN
01917 void
01918 log_reset_first_header_and_checkpoint(
01919
01920 byte* hdr_buf,
01922 ib_uint64_t start)
01925 {
01926 ulint fold;
01927 byte* buf;
01928 ib_uint64_t lsn;
01929
01930 mach_write_to_4(hdr_buf + LOG_GROUP_ID, 0);
01931 mach_write_to_8(hdr_buf + LOG_FILE_START_LSN, start);
01932
01933 lsn = start + LOG_BLOCK_HDR_SIZE;
01934
01935
01936 strcpy((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
01937 "ibbackup ");
01938 ut_sprintf_timestamp((char*) hdr_buf
01939 + (LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
01940 + (sizeof "ibbackup ") - 1));
01941 buf = hdr_buf + LOG_CHECKPOINT_1;
01942
01943 mach_write_to_8(buf + LOG_CHECKPOINT_NO, 0);
01944 mach_write_to_8(buf + LOG_CHECKPOINT_LSN, lsn);
01945
01946 mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET,
01947 LOG_FILE_HDR_SIZE + LOG_BLOCK_HDR_SIZE);
01948
01949 mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, 2 * 1024 * 1024);
01950
01951 mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, IB_ULONGLONG_MAX);
01952
01953 fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1);
01954 mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_1, fold);
01955
01956 fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
01957 LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
01958 mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_2, fold);
01959
01960
01961
01962
01963 }
01964 #endif
01965
01966 #ifndef UNIV_HOTBACKUP
01967
01969 UNIV_INTERN
01970 void
01971 log_group_read_checkpoint_info(
01972
01973 log_group_t* group,
01974 ulint field)
01975 {
01976 ut_ad(mutex_own(&(log_sys->mutex)));
01977
01978 log_sys->n_log_ios++;
01979
01980 fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, group->space_id, 0,
01981 field / UNIV_PAGE_SIZE, field % UNIV_PAGE_SIZE,
01982 OS_FILE_LOG_BLOCK_SIZE, log_sys->checkpoint_buf, NULL);
01983 }
01984
01985
01987 UNIV_INTERN
01988 void
01989 log_groups_write_checkpoint_info(void)
01990
01991 {
01992 log_group_t* group;
01993
01994 ut_ad(mutex_own(&(log_sys->mutex)));
01995
01996 group = UT_LIST_GET_FIRST(log_sys->log_groups);
01997
01998 while (group) {
01999 log_group_checkpoint(group);
02000
02001 group = UT_LIST_GET_NEXT(log_groups, group);
02002 }
02003 }
02004
02005
02011 UNIV_INTERN
02012 ibool
02013 log_checkpoint(
02014
02015 ibool sync,
02017 ibool write_always)
02023 {
02024 ib_uint64_t oldest_lsn;
02025
02026 if (recv_recovery_is_on()) {
02027 recv_apply_hashed_log_recs(TRUE);
02028 }
02029
02030 if (srv_unix_file_flush_method != SRV_UNIX_NOSYNC) {
02031 fil_flush_file_spaces(FIL_TABLESPACE);
02032 }
02033
02034 mutex_enter(&(log_sys->mutex));
02035
02036 ut_ad(!recv_no_log_write);
02037 oldest_lsn = log_buf_pool_get_oldest_modification();
02038
02039 mutex_exit(&(log_sys->mutex));
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049 log_write_up_to(oldest_lsn, LOG_WAIT_ALL_GROUPS, TRUE);
02050
02051 mutex_enter(&(log_sys->mutex));
02052
02053 if (!write_always
02054 && log_sys->last_checkpoint_lsn >= oldest_lsn) {
02055
02056 mutex_exit(&(log_sys->mutex));
02057
02058 return(TRUE);
02059 }
02060
02061 ut_ad(log_sys->flushed_to_disk_lsn >= oldest_lsn);
02062
02063 if (log_sys->n_pending_checkpoint_writes > 0) {
02064
02065
02066 mutex_exit(&(log_sys->mutex));
02067
02068 if (sync) {
02069
02070 rw_lock_s_lock(&(log_sys->checkpoint_lock));
02071 rw_lock_s_unlock(&(log_sys->checkpoint_lock));
02072 }
02073
02074 return(FALSE);
02075 }
02076
02077 log_sys->next_checkpoint_lsn = oldest_lsn;
02078
02079 #ifdef UNIV_DEBUG
02080 if (log_debug_writes) {
02081 fprintf(stderr, "Making checkpoint no %lu at lsn %"PRIu64"\n",
02082 (ulong) log_sys->next_checkpoint_no,
02083 oldest_lsn);
02084 }
02085 #endif
02086
02087 log_groups_write_checkpoint_info();
02088
02089 mutex_exit(&(log_sys->mutex));
02090
02091 if (sync) {
02092
02093 rw_lock_s_lock(&(log_sys->checkpoint_lock));
02094 rw_lock_s_unlock(&(log_sys->checkpoint_lock));
02095 }
02096
02097 return(TRUE);
02098 }
02099
02100
02102 UNIV_INTERN
02103 void
02104 log_make_checkpoint_at(
02105
02106 ib_uint64_t lsn,
02109 ibool write_always)
02116 {
02117
02118
02119 while (!log_preflush_pool_modified_pages(lsn, TRUE)) {}
02120
02121 while (!log_checkpoint(TRUE, write_always)) {}
02122 }
02123
02124
02129 static
02130 void
02131 log_checkpoint_margin(void)
02132
02133 {
02134 log_t* log = log_sys;
02135 ib_uint64_t age;
02136 ib_uint64_t checkpoint_age;
02137 ib_uint64_t advance;
02138 ib_uint64_t oldest_lsn;
02139 ibool sync;
02140 ibool checkpoint_sync;
02141 ibool do_checkpoint;
02142 ibool success;
02143 loop:
02144 sync = FALSE;
02145 checkpoint_sync = FALSE;
02146 do_checkpoint = FALSE;
02147
02148 mutex_enter(&(log->mutex));
02149 ut_ad(!recv_no_log_write);
02150
02151 if (log->check_flush_or_checkpoint == FALSE) {
02152 mutex_exit(&(log->mutex));
02153
02154 return;
02155 }
02156
02157 oldest_lsn = log_buf_pool_get_oldest_modification();
02158
02159 age = log->lsn - oldest_lsn;
02160
02161 if (age > log->max_modified_age_sync) {
02162
02163
02164
02165 sync = TRUE;
02166 advance = 2 * (age - log->max_modified_age_sync);
02167 } else if (age > log_max_modified_age_async()) {
02168
02169
02170 advance = age - log_max_modified_age_async();
02171 } else {
02172 advance = 0;
02173 }
02174
02175 checkpoint_age = log->lsn - log->last_checkpoint_lsn;
02176
02177 if (checkpoint_age > log->max_checkpoint_age) {
02178
02179
02180 checkpoint_sync = TRUE;
02181
02182 do_checkpoint = TRUE;
02183
02184 } else if (checkpoint_age > log_max_checkpoint_age_async()) {
02185
02186
02187 do_checkpoint = TRUE;
02188
02189 log->check_flush_or_checkpoint = FALSE;
02190 } else {
02191 log->check_flush_or_checkpoint = FALSE;
02192 }
02193
02194 mutex_exit(&(log->mutex));
02195
02196 if (advance) {
02197 ib_uint64_t new_oldest = oldest_lsn + advance;
02198
02199 success = log_preflush_pool_modified_pages(new_oldest, sync);
02200
02201
02202
02203
02204
02205
02206
02207 if (sync && !success) {
02208 mutex_enter(&(log->mutex));
02209
02210 log->check_flush_or_checkpoint = TRUE;
02211
02212 mutex_exit(&(log->mutex));
02213 goto loop;
02214 }
02215 }
02216
02217 if (do_checkpoint) {
02218 log_checkpoint(checkpoint_sync, FALSE);
02219
02220 if (checkpoint_sync) {
02221
02222 goto loop;
02223 }
02224 }
02225 }
02226
02227
02229 UNIV_INTERN
02230 void
02231 log_group_read_log_seg(
02232
02233 ulint type,
02234 byte* buf,
02235 log_group_t* group,
02236 ib_uint64_t start_lsn,
02237 ib_uint64_t end_lsn)
02238 {
02239 ulint len;
02240 ulint source_offset;
02241 ibool sync;
02242
02243 ut_ad(mutex_own(&(log_sys->mutex)));
02244
02245 sync = (type == LOG_RECOVER);
02246 loop:
02247 source_offset = log_group_calc_lsn_offset(start_lsn, group);
02248
02249 len = (ulint) (end_lsn - start_lsn);
02250
02251 ut_ad(len != 0);
02252
02253 if ((source_offset % group->file_size) + len > group->file_size) {
02254
02255 len = group->file_size - (source_offset % group->file_size);
02256 }
02257
02258 #ifdef UNIV_LOG_ARCHIVE
02259 if (type == LOG_ARCHIVE) {
02260
02261 log_sys->n_pending_archive_ios++;
02262 }
02263 #endif
02264
02265 log_sys->n_log_ios++;
02266
02267 fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id, 0,
02268 source_offset / UNIV_PAGE_SIZE, source_offset % UNIV_PAGE_SIZE,
02269 len, buf, NULL);
02270
02271 start_lsn += len;
02272 buf += len;
02273
02274 if (start_lsn != end_lsn) {
02275
02276 goto loop;
02277 }
02278 }
02279
02280 #ifdef UNIV_LOG_ARCHIVE
02281
02283 UNIV_INTERN
02284 void
02285 log_archived_file_name_gen(
02286
02287 char* buf,
02288 ulint ,
02291 ulint file_no)
02292 {
02293 sprintf(buf, "%sib_arch_log_%010lu", srv_arch_dir, (ulong) file_no);
02294 }
02295
02296
02298 static
02299 void
02300 log_group_archive_file_header_write(
02301
02302 log_group_t* group,
02303 ulint nth_file,
02305 ulint file_no,
02306 ib_uint64_t start_lsn)
02308 {
02309 byte* buf;
02310 ulint dest_offset;
02311
02312 ut_ad(mutex_own(&(log_sys->mutex)));
02313
02314 ut_a(nth_file < group->n_files);
02315
02316 buf = *(group->archive_file_header_bufs + nth_file);
02317
02318 mach_write_to_4(buf + LOG_GROUP_ID, group->id);
02319 mach_write_to_8(buf + LOG_FILE_START_LSN, start_lsn);
02320 mach_write_to_4(buf + LOG_FILE_NO, file_no);
02321
02322 mach_write_to_4(buf + LOG_FILE_ARCH_COMPLETED, FALSE);
02323
02324 dest_offset = nth_file * group->file_size;
02325
02326 log_sys->n_log_ios++;
02327
02328 fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->archive_space_id,
02329 dest_offset / UNIV_PAGE_SIZE,
02330 dest_offset % UNIV_PAGE_SIZE,
02331 2 * OS_FILE_LOG_BLOCK_SIZE,
02332 buf, &log_archive_io);
02333 }
02334
02335
02337 static
02338 void
02339 log_group_archive_completed_header_write(
02340
02341 log_group_t* group,
02342 ulint nth_file,
02344 ib_uint64_t end_lsn)
02345 {
02346 byte* buf;
02347 ulint dest_offset;
02348
02349 ut_ad(mutex_own(&(log_sys->mutex)));
02350 ut_a(nth_file < group->n_files);
02351
02352 buf = *(group->archive_file_header_bufs + nth_file);
02353
02354 mach_write_to_4(buf + LOG_FILE_ARCH_COMPLETED, TRUE);
02355 mach_write_to_8(buf + LOG_FILE_END_LSN, end_lsn);
02356
02357 dest_offset = nth_file * group->file_size + LOG_FILE_ARCH_COMPLETED;
02358
02359 log_sys->n_log_ios++;
02360
02361 fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->archive_space_id,
02362 dest_offset / UNIV_PAGE_SIZE,
02363 dest_offset % UNIV_PAGE_SIZE,
02364 OS_FILE_LOG_BLOCK_SIZE,
02365 buf + LOG_FILE_ARCH_COMPLETED,
02366 &log_archive_io);
02367 }
02368
02369
02371 static
02372 void
02373 log_group_archive(
02374
02375 log_group_t* group)
02376 {
02377 os_file_t file_handle;
02378 ib_uint64_t start_lsn;
02379 ib_uint64_t end_lsn;
02380 char name[1024];
02381 byte* buf;
02382 ulint len;
02383 ibool ret;
02384 ulint next_offset;
02385 ulint n_files;
02386 ulint open_mode;
02387
02388 ut_ad(mutex_own(&(log_sys->mutex)));
02389
02390 start_lsn = log_sys->archived_lsn;
02391
02392 ut_a(start_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
02393
02394 end_lsn = log_sys->next_archived_lsn;
02395
02396 ut_a(end_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
02397
02398 buf = log_sys->archive_buf;
02399
02400 n_files = 0;
02401
02402 next_offset = group->archived_offset;
02403 loop:
02404 if ((next_offset % group->file_size == 0)
02405 || (fil_space_get_size(group->archive_space_id) == 0)) {
02406
02407
02408
02409
02410 if (next_offset % group->file_size == 0) {
02411 open_mode = OS_FILE_CREATE;
02412 } else {
02413 open_mode = OS_FILE_OPEN;
02414 }
02415
02416 log_archived_file_name_gen(name, group->id,
02417 group->archived_file_no + n_files);
02418
02419 file_handle = os_file_create(innodb_file_log_key,
02420 name, open_mode,
02421 OS_FILE_AIO,
02422 OS_DATA_FILE, &ret);
02423
02424 if (!ret && (open_mode == OS_FILE_CREATE)) {
02425 file_handle = os_file_create(
02426 innodb_file_log_key, name, OS_FILE_OPEN,
02427 OS_FILE_AIO, OS_DATA_FILE, &ret);
02428 }
02429
02430 if (!ret) {
02431 fprintf(stderr,
02432 "InnoDB: Cannot create or open"
02433 " archive log file %s.\n"
02434 "InnoDB: Cannot continue operation.\n"
02435 "InnoDB: Check that the log archive"
02436 " directory exists,\n"
02437 "InnoDB: you have access rights to it, and\n"
02438 "InnoDB: there is space available.\n", name);
02439 exit(1);
02440 }
02441
02442 #ifdef UNIV_DEBUG
02443 if (log_debug_writes) {
02444 fprintf(stderr, "Created archive file %s\n", name);
02445 }
02446 #endif
02447
02448 ret = os_file_close(file_handle);
02449
02450 ut_a(ret);
02451
02452
02453
02454 fil_node_create(name, group->file_size / UNIV_PAGE_SIZE,
02455 group->archive_space_id, FALSE);
02456
02457 if (next_offset % group->file_size == 0) {
02458 log_group_archive_file_header_write(
02459 group, n_files,
02460 group->archived_file_no + n_files,
02461 start_lsn);
02462
02463 next_offset += LOG_FILE_HDR_SIZE;
02464 }
02465 }
02466
02467 len = end_lsn - start_lsn;
02468
02469 if (group->file_size < (next_offset % group->file_size) + len) {
02470
02471 len = group->file_size - (next_offset % group->file_size);
02472 }
02473
02474 #ifdef UNIV_DEBUG
02475 if (log_debug_writes) {
02476 fprintf(stderr,
02477 "Archiving starting at lsn %"PRIu64", len %lu"
02478 " to group %lu\n",
02479 start_lsn,
02480 (ulong) len, (ulong) group->id);
02481 }
02482 #endif
02483
02484 log_sys->n_pending_archive_ios++;
02485
02486 log_sys->n_log_ios++;
02487
02488 fil_io(OS_FILE_WRITE | OS_FILE_LOG, FALSE, group->archive_space_id,
02489 next_offset / UNIV_PAGE_SIZE, next_offset % UNIV_PAGE_SIZE,
02490 ut_calc_align(len, OS_FILE_LOG_BLOCK_SIZE), buf,
02491 &log_archive_io);
02492
02493 start_lsn += len;
02494 next_offset += len;
02495 buf += len;
02496
02497 if (next_offset % group->file_size == 0) {
02498 n_files++;
02499 }
02500
02501 if (end_lsn != start_lsn) {
02502
02503 goto loop;
02504 }
02505
02506 group->next_archived_file_no = group->archived_file_no + n_files;
02507 group->next_archived_offset = next_offset % group->file_size;
02508
02509 ut_a(group->next_archived_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
02510 }
02511
02512
02515 static
02516 void
02517 log_archive_groups(void)
02518
02519 {
02520 log_group_t* group;
02521
02522 ut_ad(mutex_own(&(log_sys->mutex)));
02523
02524 group = UT_LIST_GET_FIRST(log_sys->log_groups);
02525
02526 log_group_archive(group);
02527 }
02528
02529
02532 static
02533 void
02534 log_archive_write_complete_groups(void)
02535
02536 {
02537 log_group_t* group;
02538 ulint end_offset;
02539 ulint trunc_files;
02540 ulint n_files;
02541 ib_uint64_t start_lsn;
02542 ib_uint64_t end_lsn;
02543 ulint i;
02544
02545 ut_ad(mutex_own(&(log_sys->mutex)));
02546
02547 group = UT_LIST_GET_FIRST(log_sys->log_groups);
02548
02549 group->archived_file_no = group->next_archived_file_no;
02550 group->archived_offset = group->next_archived_offset;
02551
02552
02553
02554
02555 n_files = (UNIV_PAGE_SIZE
02556 * fil_space_get_size(group->archive_space_id))
02557 / group->file_size;
02558 ut_ad(n_files > 0);
02559
02560 end_offset = group->archived_offset;
02561
02562 if (end_offset % group->file_size == 0) {
02563
02564 trunc_files = n_files;
02565 } else {
02566 trunc_files = n_files - 1;
02567 }
02568
02569 #ifdef UNIV_DEBUG
02570 if (log_debug_writes && trunc_files) {
02571 fprintf(stderr,
02572 "Complete file(s) archived to group %lu\n",
02573 (ulong) group->id);
02574 }
02575 #endif
02576
02577
02578 start_lsn = log_sys->next_archived_lsn
02579 - (end_offset - LOG_FILE_HDR_SIZE + trunc_files
02580 * (group->file_size - LOG_FILE_HDR_SIZE));
02581 end_lsn = start_lsn;
02582
02583 for (i = 0; i < trunc_files; i++) {
02584
02585 end_lsn += group->file_size - LOG_FILE_HDR_SIZE;
02586
02587
02588
02589
02590 log_group_archive_completed_header_write(group, i, end_lsn);
02591 }
02592
02593 fil_space_truncate_start(group->archive_space_id,
02594 trunc_files * group->file_size);
02595
02596 #ifdef UNIV_DEBUG
02597 if (log_debug_writes) {
02598 fputs("Archiving writes completed\n", stderr);
02599 }
02600 #endif
02601 }
02602
02603
02605 static
02606 void
02607 log_archive_check_completion_low(void)
02608
02609 {
02610 ut_ad(mutex_own(&(log_sys->mutex)));
02611
02612 if (log_sys->n_pending_archive_ios == 0
02613 && log_sys->archiving_phase == LOG_ARCHIVE_READ) {
02614
02615 #ifdef UNIV_DEBUG
02616 if (log_debug_writes) {
02617 fputs("Archiving read completed\n", stderr);
02618 }
02619 #endif
02620
02621
02622
02623 log_sys->archiving_phase = LOG_ARCHIVE_WRITE;
02624
02625 log_archive_groups();
02626 }
02627
02628 if (log_sys->n_pending_archive_ios == 0
02629 && log_sys->archiving_phase == LOG_ARCHIVE_WRITE) {
02630
02631 log_archive_write_complete_groups();
02632
02633 log_sys->archived_lsn = log_sys->next_archived_lsn;
02634
02635 rw_lock_x_unlock_gen(&(log_sys->archive_lock), LOG_ARCHIVE);
02636 }
02637 }
02638
02639
02641 static
02642 void
02643 log_io_complete_archive(void)
02644
02645 {
02646 log_group_t* group;
02647
02648 mutex_enter(&(log_sys->mutex));
02649
02650 group = UT_LIST_GET_FIRST(log_sys->log_groups);
02651
02652 mutex_exit(&(log_sys->mutex));
02653
02654 fil_flush(group->archive_space_id);
02655
02656 mutex_enter(&(log_sys->mutex));
02657
02658 ut_ad(log_sys->n_pending_archive_ios > 0);
02659
02660 log_sys->n_pending_archive_ios--;
02661
02662 log_archive_check_completion_low();
02663
02664 mutex_exit(&(log_sys->mutex));
02665 }
02666
02667
02670 UNIV_INTERN
02671 ibool
02672 log_archive_do(
02673
02674 ibool sync,
02675 ulint* n_bytes)
02677 {
02678 ibool calc_new_limit;
02679 ib_uint64_t start_lsn;
02680 ib_uint64_t limit_lsn;
02681
02682 calc_new_limit = TRUE;
02683 loop:
02684 mutex_enter(&(log_sys->mutex));
02685
02686 switch (log_sys->archiving_state) {
02687 case LOG_ARCH_OFF:
02688 arch_none:
02689 mutex_exit(&(log_sys->mutex));
02690
02691 *n_bytes = 0;
02692
02693 return(TRUE);
02694 case LOG_ARCH_STOPPED:
02695 case LOG_ARCH_STOPPING2:
02696 mutex_exit(&(log_sys->mutex));
02697
02698 os_event_wait(log_sys->archiving_on);
02699
02700 goto loop;
02701 }
02702
02703 start_lsn = log_sys->archived_lsn;
02704
02705 if (calc_new_limit) {
02706 ut_a(log_sys->archive_buf_size % OS_FILE_LOG_BLOCK_SIZE == 0);
02707 limit_lsn = start_lsn + log_sys->archive_buf_size;
02708
02709 *n_bytes = log_sys->archive_buf_size;
02710
02711 if (limit_lsn >= log_sys->lsn) {
02712
02713 limit_lsn = ut_uint64_align_down(
02714 log_sys->lsn, OS_FILE_LOG_BLOCK_SIZE);
02715 }
02716 }
02717
02718 if (log_sys->archived_lsn >= limit_lsn) {
02719
02720 goto arch_none;
02721 }
02722
02723 if (log_sys->written_to_all_lsn < limit_lsn) {
02724
02725 mutex_exit(&(log_sys->mutex));
02726
02727 log_write_up_to(limit_lsn, LOG_WAIT_ALL_GROUPS, TRUE);
02728
02729 calc_new_limit = FALSE;
02730
02731 goto loop;
02732 }
02733
02734 if (log_sys->n_pending_archive_ios > 0) {
02735
02736
02737 mutex_exit(&(log_sys->mutex));
02738
02739 if (sync) {
02740 rw_lock_s_lock(&(log_sys->archive_lock));
02741 rw_lock_s_unlock(&(log_sys->archive_lock));
02742 }
02743
02744 *n_bytes = log_sys->archive_buf_size;
02745
02746 return(FALSE);
02747 }
02748
02749 rw_lock_x_lock_gen(&(log_sys->archive_lock), LOG_ARCHIVE);
02750
02751 log_sys->archiving_phase = LOG_ARCHIVE_READ;
02752
02753 log_sys->next_archived_lsn = limit_lsn;
02754
02755 #ifdef UNIV_DEBUG
02756 if (log_debug_writes) {
02757 fprintf(stderr,
02758 "Archiving from lsn %"PRIu64" to lsn %"PRIu64"\n",
02759 log_sys->archived_lsn, limit_lsn);
02760 }
02761 #endif
02762
02763
02764
02765 log_group_read_log_seg(LOG_ARCHIVE, log_sys->archive_buf,
02766 UT_LIST_GET_FIRST(log_sys->log_groups),
02767 start_lsn, limit_lsn);
02768
02769 mutex_exit(&(log_sys->mutex));
02770
02771 if (sync) {
02772 rw_lock_s_lock(&(log_sys->archive_lock));
02773 rw_lock_s_unlock(&(log_sys->archive_lock));
02774 }
02775
02776 *n_bytes = log_sys->archive_buf_size;
02777
02778 return(TRUE);
02779 }
02780
02781
02784 static
02785 void
02786 log_archive_all(void)
02787
02788 {
02789 ib_uint64_t present_lsn;
02790 ulint dummy;
02791
02792 mutex_enter(&(log_sys->mutex));
02793
02794 if (log_sys->archiving_state == LOG_ARCH_OFF) {
02795 mutex_exit(&(log_sys->mutex));
02796
02797 return;
02798 }
02799
02800 present_lsn = log_sys->lsn;
02801
02802 mutex_exit(&(log_sys->mutex));
02803
02804 log_pad_current_log_block();
02805
02806 for (;;) {
02807 mutex_enter(&(log_sys->mutex));
02808
02809 if (present_lsn <= log_sys->archived_lsn) {
02810
02811 mutex_exit(&(log_sys->mutex));
02812
02813 return;
02814 }
02815
02816 mutex_exit(&(log_sys->mutex));
02817
02818 log_archive_do(TRUE, &dummy);
02819 }
02820 }
02821
02822
02825 static
02826 void
02827 log_archive_close_groups(
02828
02829 ibool increment_file_count)
02831 {
02832 log_group_t* group;
02833 ulint trunc_len;
02834
02835 ut_ad(mutex_own(&(log_sys->mutex)));
02836
02837 if (log_sys->archiving_state == LOG_ARCH_OFF) {
02838
02839 return;
02840 }
02841
02842 group = UT_LIST_GET_FIRST(log_sys->log_groups);
02843
02844 trunc_len = UNIV_PAGE_SIZE
02845 * fil_space_get_size(group->archive_space_id);
02846 if (trunc_len > 0) {
02847 ut_a(trunc_len == group->file_size);
02848
02849
02850
02851
02852 log_group_archive_completed_header_write(
02853 group, 0, log_sys->archived_lsn);
02854
02855 fil_space_truncate_start(group->archive_space_id,
02856 trunc_len);
02857 if (increment_file_count) {
02858 group->archived_offset = 0;
02859 group->archived_file_no += 2;
02860 }
02861
02862 #ifdef UNIV_DEBUG
02863 if (log_debug_writes) {
02864 fprintf(stderr,
02865 "Incrementing arch file no to %lu"
02866 " in log group %lu\n",
02867 (ulong) group->archived_file_no + 2,
02868 (ulong) group->id);
02869 }
02870 #endif
02871 }
02872 }
02873
02874
02880 UNIV_INTERN
02881 ulint
02882 log_archive_stop(void)
02883
02884 {
02885 ibool success;
02886
02887 mutex_enter(&(log_sys->mutex));
02888
02889 if (log_sys->archiving_state != LOG_ARCH_ON) {
02890
02891 mutex_exit(&(log_sys->mutex));
02892
02893 return(DB_ERROR);
02894 }
02895
02896 log_sys->archiving_state = LOG_ARCH_STOPPING;
02897
02898 mutex_exit(&(log_sys->mutex));
02899
02900 log_archive_all();
02901
02902 mutex_enter(&(log_sys->mutex));
02903
02904 log_sys->archiving_state = LOG_ARCH_STOPPING2;
02905 os_event_reset(log_sys->archiving_on);
02906
02907 mutex_exit(&(log_sys->mutex));
02908
02909
02910
02911 rw_lock_s_lock(&(log_sys->archive_lock));
02912 rw_lock_s_unlock(&(log_sys->archive_lock));
02913
02914 mutex_enter(&(log_sys->mutex));
02915
02916
02917
02918
02919 log_archive_close_groups(TRUE);
02920
02921 mutex_exit(&(log_sys->mutex));
02922
02923
02924
02925
02926 success = FALSE;
02927
02928 while (!success) {
02929 success = log_checkpoint(TRUE, TRUE);
02930 }
02931
02932 mutex_enter(&(log_sys->mutex));
02933
02934 log_sys->archiving_state = LOG_ARCH_STOPPED;
02935
02936 mutex_exit(&(log_sys->mutex));
02937
02938 return(DB_SUCCESS);
02939 }
02940
02941
02944 UNIV_INTERN
02945 ulint
02946 log_archive_start(void)
02947
02948 {
02949 mutex_enter(&(log_sys->mutex));
02950
02951 if (log_sys->archiving_state != LOG_ARCH_STOPPED) {
02952
02953 mutex_exit(&(log_sys->mutex));
02954
02955 return(DB_ERROR);
02956 }
02957
02958 log_sys->archiving_state = LOG_ARCH_ON;
02959
02960 os_event_set(log_sys->archiving_on);
02961
02962 mutex_exit(&(log_sys->mutex));
02963
02964 return(DB_SUCCESS);
02965 }
02966
02967
02970 UNIV_INTERN
02971 ulint
02972 log_archive_noarchivelog(void)
02973
02974 {
02975 loop:
02976 mutex_enter(&(log_sys->mutex));
02977
02978 if (log_sys->archiving_state == LOG_ARCH_STOPPED
02979 || log_sys->archiving_state == LOG_ARCH_OFF) {
02980
02981 log_sys->archiving_state = LOG_ARCH_OFF;
02982
02983 os_event_set(log_sys->archiving_on);
02984
02985 mutex_exit(&(log_sys->mutex));
02986
02987 return(DB_SUCCESS);
02988 }
02989
02990 mutex_exit(&(log_sys->mutex));
02991
02992 log_archive_stop();
02993
02994 os_thread_sleep(500000);
02995
02996 goto loop;
02997 }
02998
02999
03002 UNIV_INTERN
03003 ulint
03004 log_archive_archivelog(void)
03005
03006 {
03007 mutex_enter(&(log_sys->mutex));
03008
03009 if (log_sys->archiving_state == LOG_ARCH_OFF) {
03010
03011 log_sys->archiving_state = LOG_ARCH_ON;
03012
03013 log_sys->archived_lsn
03014 = ut_uint64_align_down(log_sys->lsn,
03015 OS_FILE_LOG_BLOCK_SIZE);
03016 mutex_exit(&(log_sys->mutex));
03017
03018 return(DB_SUCCESS);
03019 }
03020
03021 mutex_exit(&(log_sys->mutex));
03022
03023 return(DB_ERROR);
03024 }
03025
03026
03030 static
03031 void
03032 log_archive_margin(void)
03033
03034 {
03035 log_t* log = log_sys;
03036 ulint age;
03037 ibool sync;
03038 ulint dummy;
03039 loop:
03040 mutex_enter(&(log->mutex));
03041
03042 if (log->archiving_state == LOG_ARCH_OFF) {
03043 mutex_exit(&(log->mutex));
03044
03045 return;
03046 }
03047
03048 age = log->lsn - log->archived_lsn;
03049
03050 if (age > log->max_archived_lsn_age) {
03051
03052
03053
03054 sync = TRUE;
03055
03056 } else if (age > log->max_archived_lsn_age_async) {
03057
03058
03059
03060 sync = FALSE;
03061 } else {
03062
03063
03064 mutex_exit(&(log->mutex));
03065
03066 return;
03067 }
03068
03069 mutex_exit(&(log->mutex));
03070
03071 log_archive_do(sync, &dummy);
03072
03073 if (sync == TRUE) {
03074
03075
03076 goto loop;
03077 }
03078 }
03079 #endif
03080
03081
03086 UNIV_INTERN
03087 void
03088 log_check_margins(void)
03089
03090 {
03091 loop:
03092 log_flush_margin();
03093
03094 log_checkpoint_margin();
03095
03096 #ifdef UNIV_LOG_ARCHIVE
03097 log_archive_margin();
03098 #endif
03099
03100 mutex_enter(&(log_sys->mutex));
03101 ut_ad(!recv_no_log_write);
03102
03103 if (log_sys->check_flush_or_checkpoint) {
03104
03105 mutex_exit(&(log_sys->mutex));
03106
03107 goto loop;
03108 }
03109
03110 mutex_exit(&(log_sys->mutex));
03111 }
03112
03113
03118 UNIV_INTERN
03119 void
03120 logs_empty_and_mark_files_at_shutdown(void)
03121
03122 {
03123 ib_uint64_t lsn;
03124 ulint arch_log_no;
03125
03126 if (srv_print_verbose_log) {
03127 ut_print_timestamp(stderr);
03128 fprintf(stderr, " InnoDB: Starting shutdown...\n");
03129 }
03130
03131
03132
03133 srv_shutdown_state = SRV_SHUTDOWN_CLEANUP;
03134 loop:
03135 os_thread_sleep(100000);
03136
03137 mutex_enter(&kernel_mutex);
03138
03139
03140
03141
03142
03143 if (srv_fast_shutdown < 2
03144 && (srv_error_monitor_active
03145 || srv_lock_timeout_active
03146 || srv_monitor_active)) {
03147
03148 mutex_exit(&kernel_mutex);
03149
03150 os_event_set(srv_error_event);
03151 os_event_set(srv_monitor_event);
03152 os_event_set(srv_timeout_event);
03153
03154 goto loop;
03155 }
03156
03157
03158
03159
03160
03161 if (! srv_apply_log_only) {
03162 if (trx_n_mysql_transactions > 0
03163 || UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
03164
03165 mutex_exit(&kernel_mutex);
03166
03167 goto loop;
03168 }
03169 }
03170
03171 if (srv_fast_shutdown == 2) {
03172
03173
03174
03175
03176
03177
03178
03179
03180 log_buffer_flush_to_disk();
03181
03182 mutex_exit(&kernel_mutex);
03183
03184 return;
03185 }
03186
03187 mutex_exit(&kernel_mutex);
03188
03189
03190
03191 if (srv_is_any_background_thread_active()) {
03192 goto loop;
03193 }
03194
03195 mutex_enter(&(log_sys->mutex));
03196
03197 if (log_sys->n_pending_checkpoint_writes
03198 #ifdef UNIV_LOG_ARCHIVE
03199 || log_sys->n_pending_archive_ios
03200 #endif
03201 || log_sys->n_pending_writes) {
03202
03203 mutex_exit(&(log_sys->mutex));
03204
03205 goto loop;
03206 }
03207
03208 mutex_exit(&(log_sys->mutex));
03209
03210 if (!buf_pool_check_no_pending_io()) {
03211
03212 goto loop;
03213 }
03214
03215 #ifdef UNIV_LOG_ARCHIVE
03216 log_archive_all();
03217 #endif
03218
03219 log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
03220
03221 mutex_enter(&(log_sys->mutex));
03222
03223 lsn = log_sys->lsn;
03224
03225 if (lsn != log_sys->last_checkpoint_lsn
03226 #ifdef UNIV_LOG_ARCHIVE
03227 || (srv_log_archive_on
03228 && lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE)
03229 #endif
03230 ) {
03231
03232 mutex_exit(&(log_sys->mutex));
03233
03234 goto loop;
03235 }
03236
03237 arch_log_no = 0;
03238
03239 #ifdef UNIV_LOG_ARCHIVE
03240 UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no;
03241
03242 if (0 == UT_LIST_GET_FIRST(log_sys->log_groups)->archived_offset) {
03243
03244 arch_log_no--;
03245 }
03246
03247 log_archive_close_groups(TRUE);
03248 #endif
03249
03250 mutex_exit(&(log_sys->mutex));
03251
03252
03253 if (srv_is_any_background_thread_active()) {
03254 fprintf(stderr,
03255 "InnoDB: Warning: some background thread woke up"
03256 " during shutdown\n");
03257
03258 goto loop;
03259 }
03260
03261 fil_flush_file_spaces(FIL_TABLESPACE);
03262 fil_flush_file_spaces(FIL_LOG);
03263
03264
03265
03266
03267
03268
03269 if (!buf_all_freed()) {
03270
03271 goto loop;
03272 }
03273
03274 srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
03275
03276
03277 ut_a(!srv_is_any_background_thread_active());
03278
03279 ut_a(buf_all_freed());
03280 ut_a(lsn == log_sys->lsn);
03281
03282 if (lsn < srv_start_lsn) {
03283 drizzled::errmsg_printf(drizzled::error::ERROR,
03284 "InnoDB: Error: log sequence number at shutdown %"PRIu64" is lower than at startup %"PRIu64"!",
03285 lsn, srv_start_lsn);
03286 }
03287
03288 srv_shutdown_lsn = lsn;
03289
03290 fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
03291
03292 fil_flush_file_spaces(FIL_TABLESPACE);
03293
03294 fil_close_all_files();
03295
03296
03297 ut_a(!srv_is_any_background_thread_active());
03298
03299 ut_a(buf_all_freed());
03300 ut_a(lsn == log_sys->lsn);
03301 }
03302
03303 #ifdef UNIV_LOG_DEBUG
03304
03307 UNIV_INTERN
03308 ibool
03309 log_check_log_recs(
03310
03311 const byte* buf,
03314 ulint len,
03315 ib_uint64_t buf_start_lsn)
03316 {
03317 ib_uint64_t contiguous_lsn;
03318 ib_uint64_t scanned_lsn;
03319 const byte* start;
03320 const byte* end;
03321 byte* buf1;
03322 byte* scan_buf;
03323
03324 ut_ad(mutex_own(&(log_sys->mutex)));
03325
03326 if (len == 0) {
03327
03328 return(TRUE);
03329 }
03330
03331 start = ut_align_down(buf, OS_FILE_LOG_BLOCK_SIZE);
03332 end = ut_align(buf + len, OS_FILE_LOG_BLOCK_SIZE);
03333
03334 buf1 = mem_alloc((end - start) + OS_FILE_LOG_BLOCK_SIZE);
03335 scan_buf = ut_align(buf1, OS_FILE_LOG_BLOCK_SIZE);
03336
03337 ut_memcpy(scan_buf, start, end - start);
03338
03339 recv_scan_log_recs((buf_pool_get_n_pages()
03340 - (recv_n_pool_free_frames * srv_buf_pool_instances))
03341 * UNIV_PAGE_SIZE, FALSE, scan_buf, end - start,
03342 ut_uint64_align_down(buf_start_lsn,
03343 OS_FILE_LOG_BLOCK_SIZE),
03344 &contiguous_lsn, &scanned_lsn);
03345
03346 ut_a(scanned_lsn == buf_start_lsn + len);
03347 ut_a(recv_sys->recovered_lsn == scanned_lsn);
03348
03349 mem_free(buf1);
03350
03351 return(TRUE);
03352 }
03353 #endif
03354
03355
03358 UNIV_INTERN
03359 ibool
03360 log_peek_lsn(
03361
03362 ib_uint64_t* lsn)
03363 {
03364 if (0 == mutex_enter_nowait(&(log_sys->mutex))) {
03365 *lsn = log_sys->lsn;
03366
03367 mutex_exit(&(log_sys->mutex));
03368
03369 return(TRUE);
03370 }
03371
03372 return(FALSE);
03373 }
03374
03375
03377 UNIV_INTERN
03378 void
03379 log_print(
03380
03381 FILE* file)
03382 {
03383 double time_elapsed;
03384 time_t current_time;
03385
03386 mutex_enter(&(log_sys->mutex));
03387
03388 fprintf(file,
03389 "Log sequence number %"PRIu64"\n"
03390 "Log flushed up to %"PRIu64"\n"
03391 "Last checkpoint at %"PRIu64"\n",
03392 log_sys->lsn,
03393 log_sys->flushed_to_disk_lsn,
03394 log_sys->last_checkpoint_lsn);
03395
03396 fprintf(file,
03397 "Max checkpoint age %lu\n"
03398 "Checkpoint age target %lu\n"
03399 "Modified age %"PRIu64"\n"
03400 "Checkpoint age %"PRIu64"\n",
03401 log_sys->max_checkpoint_age,
03402 log_max_checkpoint_age_async(),
03403 log_sys->lsn - log_buf_pool_get_oldest_modification(),
03404 log_sys->lsn - log_sys->last_checkpoint_lsn);
03405
03406 current_time = time(NULL);
03407
03408 time_elapsed = 0.001 + difftime(current_time,
03409 log_sys->last_printout_time);
03410 fprintf(file,
03411 "%lu pending log writes, %lu pending chkp writes\n"
03412 "%lu log i/o's done, %.2f log i/o's/second\n",
03413 (ulong) log_sys->n_pending_writes,
03414 (ulong) log_sys->n_pending_checkpoint_writes,
03415 (ulong) log_sys->n_log_ios,
03416 ((log_sys->n_log_ios - log_sys->n_log_ios_old)
03417 / time_elapsed));
03418
03419 log_sys->n_log_ios_old = log_sys->n_log_ios;
03420 log_sys->last_printout_time = current_time;
03421
03422 mutex_exit(&(log_sys->mutex));
03423 }
03424
03425
03427 UNIV_INTERN
03428 void
03429 log_refresh_stats(void)
03430
03431 {
03432 log_sys->n_log_ios_old = log_sys->n_log_ios;
03433 log_sys->last_printout_time = time(NULL);
03434 }
03435
03436
03437
03438 static
03439 void
03440 log_group_close(
03441
03442 log_group_t* group)
03443 {
03444 ulint i;
03445
03446 for (i = 0; i < group->n_files; i++) {
03447 mem_free(group->file_header_bufs_ptr[i]);
03448 #ifdef UNIV_LOG_ARCHIVE
03449 mem_free(group->archive_file_header_bufs_ptr[i]);
03450 #endif
03451 }
03452
03453 mem_free(group->file_header_bufs_ptr);
03454 mem_free(group->file_header_bufs);
03455
03456 #ifdef UNIV_LOG_ARCHIVE
03457 mem_free(group->archive_file_header_bufs_ptr);
03458 mem_free(group->archive_file_header_bufs);
03459 #endif
03460
03461 mem_free(group->checkpoint_buf_ptr);
03462
03463 mem_free(group);
03464 }
03465
03466
03467
03468 UNIV_INTERN
03469 void
03470 log_shutdown(void)
03471
03472 {
03473 log_group_t* group;
03474
03475 group = UT_LIST_GET_FIRST(log_sys->log_groups);
03476
03477 while (UT_LIST_GET_LEN(log_sys->log_groups) > 0) {
03478 log_group_t* prev_group = group;
03479
03480 group = UT_LIST_GET_NEXT(log_groups, group);
03481 UT_LIST_REMOVE(log_groups, log_sys->log_groups, prev_group);
03482
03483 log_group_close(prev_group);
03484 }
03485
03486 mem_free(log_sys->buf_ptr);
03487 log_sys->buf_ptr = NULL;
03488 log_sys->buf = NULL;
03489 mem_free(log_sys->checkpoint_buf_ptr);
03490 log_sys->checkpoint_buf_ptr = NULL;
03491 log_sys->checkpoint_buf = NULL;
03492
03493 os_event_free(log_sys->no_flush_event);
03494 os_event_free(log_sys->one_flushed_event);
03495
03496 rw_lock_free(&log_sys->checkpoint_lock);
03497
03498 mutex_free(&log_sys->mutex);
03499
03500 #ifdef UNIV_LOG_ARCHIVE
03501 rw_lock_free(&log_sys->archive_lock);
03502 os_event_create(log_sys->archiving_on);
03503 #endif
03504
03505 #ifdef UNIV_LOG_DEBUG
03506 recv_sys_debug_free();
03507 #endif
03508
03509 recv_sys_close();
03510 }
03511
03512
03513
03514 UNIV_INTERN
03515 void
03516 log_mem_free(void)
03517
03518 {
03519 if (log_sys != NULL) {
03520 recv_sys_mem_free();
03521 mem_free(log_sys);
03522
03523 log_sys = NULL;
03524 }
03525 }
03526 #endif