53
53
/* Current free limit of space 0; protected by the log sys mutex; 0 means
55
UNIV_INTERN ulint log_fsp_current_free_limit = 0;
55
ulint log_fsp_current_free_limit = 0;
57
57
/* Global log system variable */
58
UNIV_INTERN log_t* log_sys = NULL;
58
log_t* log_sys = NULL;
61
UNIV_INTERN ibool log_do_write = TRUE;
61
ibool log_do_write = TRUE;
63
UNIV_INTERN ibool log_debug_writes = FALSE;
63
ibool log_debug_writes = FALSE;
64
64
#endif /* UNIV_DEBUG */
66
66
/* These control how often we print warnings if the last checkpoint is too
68
UNIV_INTERN ibool log_has_printed_chkp_warning = FALSE;
69
UNIV_INTERN time_t log_last_warning_time;
68
ibool log_has_printed_chkp_warning = FALSE;
69
time_t log_last_warning_time;
71
71
#ifdef UNIV_LOG_ARCHIVE
72
72
/* Pointer to this variable is used as the i/o-message when we do i/o to an
74
UNIV_INTERN byte log_archive_io;
75
75
#endif /* UNIV_LOG_ARCHIVE */
77
77
/* A margin for free space in the log buffer before a log entry is catenated */
102
102
/* Extra margin, in addition to one log file, used in archiving */
103
103
#define LOG_ARCHIVE_EXTRA_MARGIN (4 * UNIV_PAGE_SIZE)
105
#ifdef UNIV_LOG_ARCHIVE
106
105
/* This parameter controls asynchronous writing to the archive */
107
106
#define LOG_ARCHIVE_RATIO_ASYNC 16
108
/* Codes used in unlocking flush latches */
109
#define LOG_UNLOCK_NONE_FLUSHED_LOCK 1
110
#define LOG_UNLOCK_FLUSH_LOCK 2
109
112
/* States of an archiving operation */
110
113
#define LOG_ARCHIVE_READ 1
111
114
#define LOG_ARCHIVE_WRITE 2
113
#endif /* UNIV_LOG_ARCHIVE */
115
/* Codes used in unlocking flush latches */
116
#define LOG_UNLOCK_NONE_FLUSHED_LOCK 1
117
#define LOG_UNLOCK_FLUSH_LOCK 2
119
116
/**********************************************************
120
117
Completes a checkpoint write i/o to a log file. */
135
132
Sets the global variable log_fsp_current_free_limit. Also makes a checkpoint,
136
133
so that we know that the limit has been written to a log checkpoint field
140
137
log_fsp_current_free_limit_set_and_checkpoint(
141
138
/*==========================================*/
162
159
Returns the oldest modified block lsn in the pool, or log_sys->lsn if none
166
163
log_buf_pool_get_oldest_modification(void)
167
164
/*======================================*/
171
168
ut_ad(mutex_own(&(log_sys->mutex)));
173
170
lsn = buf_pool_get_oldest_modification();
172
if (ut_dulint_is_zero(lsn)) {
177
174
lsn = log_sys->lsn;
228
225
#ifdef UNIV_LOG_ARCHIVE
229
226
if (log->archiving_state != LOG_ARCH_OFF) {
231
archived_lsn_age = log->lsn - log->archived_lsn;
228
archived_lsn_age = ut_dulint_minus(log->lsn,
232
230
if (archived_lsn_age + len_upper_limit
233
231
> log->max_archived_lsn_age) {
234
232
/* Not enough free archived space in log groups: do a
304
302
log_sys->next_checkpoint_no);
305
303
len += LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE;
305
log->lsn = ut_dulint_add(log->lsn, len);
309
307
/* Initialize the next block header */
310
308
log_block_init(log_block + OS_FILE_LOG_BLOCK_SIZE, log->lsn);
310
log->lsn = ut_dulint_add(log->lsn, len);
315
313
log->buf_free += len;
360
358
log->check_flush_or_checkpoint = TRUE;
363
checkpoint_age = lsn - log->last_checkpoint_lsn;
361
checkpoint_age = ut_dulint_minus(lsn, log->last_checkpoint_lsn);
365
363
if (checkpoint_age >= log->log_group_capacity) {
366
364
/* TODO: split btr_store_big_rec_extern_fields() into small
399
397
oldest_lsn = buf_pool_get_oldest_modification();
402
|| lsn - oldest_lsn > log->max_modified_age_async
399
if (ut_dulint_is_zero(oldest_lsn)
400
|| (ut_dulint_minus(lsn, oldest_lsn)
401
> log->max_modified_age_async)
403
402
|| checkpoint_age > log->max_checkpoint_age_async) {
405
404
log->check_flush_or_checkpoint = TRUE;
423
422
log_pad_current_log_block(void)
424
423
/*===========================*/
426
byte b = MLOG_DUMMY_RECORD;
425
byte b = MLOG_DUMMY_RECORD;
431
430
/* We retrieve lsn only because otherwise gcc crashed on HP-UX */
432
431
lsn = log_reserve_and_open(OS_FILE_LOG_BLOCK_SIZE);
447
ut_a(lsn % OS_FILE_LOG_BLOCK_SIZE == LOG_BLOCK_HDR_SIZE);
446
ut_a((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
447
== LOG_BLOCK_HDR_SIZE);
449
449
#endif /* UNIV_LOG_ARCHIVE */
451
451
/**********************************************************
452
452
Calculates the data capacity of a log group, when the log file headers are not
456
456
log_group_get_capacity(
457
457
/*===================*/
503
503
log_group_calc_lsn_offset(
504
504
/*======================*/
505
505
/* out: offset within the log group */
506
ib_uint64_t lsn, /* in: lsn, must be within 4 GB of
506
dulint lsn, /* in: lsn, must be within 4 GB of
508
508
log_group_t* group) /* in: log group */
511
ib_int64_t gr_lsn_size_offset;
512
ib_int64_t difference;
513
ib_int64_t group_size;
511
ib_longlong gr_lsn_size_offset;
512
ib_longlong difference;
513
ib_longlong group_size;
516
516
ut_ad(mutex_own(&(log_sys->mutex)));
521
521
gr_lsn = group->lsn;
523
gr_lsn_size_offset = (ib_int64_t)
523
gr_lsn_size_offset = (ib_longlong)
524
524
log_group_calc_size_offset(group->lsn_offset, group);
526
group_size = (ib_int64_t) log_group_get_capacity(group);
530
difference = (ib_int64_t) (lsn - gr_lsn);
526
group_size = (ib_longlong) log_group_get_capacity(group);
528
if (ut_dulint_cmp(lsn, gr_lsn) >= 0) {
530
difference = (ib_longlong) ut_dulint_minus(lsn, gr_lsn);
532
difference = (ib_int64_t) (gr_lsn - lsn);
532
difference = (ib_longlong) ut_dulint_minus(gr_lsn, lsn);
534
534
difference = difference % group_size;
539
539
offset = (gr_lsn_size_offset + difference) % group_size;
541
ut_a(offset < (((ib_int64_t) 1) << 32)); /* offset must be < 4 GB */
541
ut_a(offset < (((ib_longlong) 1) << 32)); /* offset must be < 4 GB */
543
543
/* fprintf(stderr,
544
544
"Offset is %lu gr_lsn_offset is %lu difference is %lu\n",
551
551
/***********************************************************************
552
552
Calculates where in log files we find a specified lsn. */
555
555
log_calc_where_lsn_is(
556
556
/*==================*/
557
557
/* out: log file number */
558
ib_int64_t* log_file_offset, /* out: offset in that file
558
ib_longlong* log_file_offset, /* out: offset in that file
559
559
(including the header) */
560
ib_uint64_t first_header_lsn, /* in: first log file start
560
dulint first_header_lsn, /* in: first log file start
562
ib_uint64_t lsn, /* in: lsn whose position to
562
dulint lsn, /* in: lsn whose position to
564
564
ulint n_log_files, /* in: total number of log
566
ib_int64_t log_file_size) /* in: log file size
566
ib_longlong log_file_size) /* in: log file size
567
567
(including the header) */
569
ib_int64_t capacity = log_file_size - LOG_FILE_HDR_SIZE;
570
ib_longlong ib_first_header_lsn;
571
ib_longlong capacity = log_file_size - LOG_FILE_HDR_SIZE;
571
ib_int64_t add_this_many;
573
if (lsn < first_header_lsn) {
574
add_this_many = 1 + (first_header_lsn - lsn)
575
/ (capacity * (ib_int64_t)n_log_files);
577
* capacity * (ib_int64_t)n_log_files;
573
ib_longlong add_this_many;
575
ib_lsn = ut_conv_dulint_to_longlong(lsn);
576
ib_first_header_lsn = ut_conv_dulint_to_longlong(first_header_lsn);
578
if (ib_lsn < ib_first_header_lsn) {
579
add_this_many = 1 + (ib_first_header_lsn - ib_lsn)
580
/ (capacity * (ib_longlong)n_log_files);
581
ib_lsn += add_this_many
582
* capacity * (ib_longlong)n_log_files;
580
ut_a(lsn >= first_header_lsn);
585
ut_a(ib_lsn >= ib_first_header_lsn);
582
file_no = ((ulint)((lsn - first_header_lsn) / capacity))
587
file_no = ((ulint)((ib_lsn - ib_first_header_lsn) / capacity))
584
*log_file_offset = (lsn - first_header_lsn) % capacity;
589
*log_file_offset = (ib_lsn - ib_first_header_lsn) % capacity;
586
591
*log_file_offset = *log_file_offset + LOG_FILE_HDR_SIZE;
592
597
Sets the field values in group to correspond to a given lsn. For this function
593
598
to work, the values must already be correctly initialized to correspond to
594
599
some lsn, for instance, a checkpoint lsn. */
597
602
log_group_set_fields(
598
603
/*=================*/
599
604
log_group_t* group, /* in: group */
600
ib_uint64_t lsn) /* in: lsn for which the values should be
605
dulint lsn) /* in: lsn for which the values should be
603
608
group->lsn_offset = log_group_calc_lsn_offset(lsn, group);
763
768
log_sys->buf_next_to_write = 0;
765
log_sys->write_lsn = 0;
766
log_sys->current_flush_lsn = 0;
767
log_sys->flushed_to_disk_lsn = 0;
770
log_sys->write_lsn = ut_dulint_zero;
771
log_sys->current_flush_lsn = ut_dulint_zero;
772
log_sys->flushed_to_disk_lsn = ut_dulint_zero;
769
774
log_sys->written_to_some_lsn = log_sys->lsn;
770
775
log_sys->written_to_all_lsn = log_sys->lsn;
782
787
/*----------------------------*/
783
788
log_sys->adm_checkpoint_interval = ULINT_MAX;
785
log_sys->next_checkpoint_no = 0;
790
log_sys->next_checkpoint_no = ut_dulint_zero;
786
791
log_sys->last_checkpoint_lsn = log_sys->lsn;
787
792
log_sys->n_pending_checkpoint_writes = 0;
798
803
/* Under MySQL, log archiving is always off */
799
804
log_sys->archiving_state = LOG_ARCH_OFF;
800
805
log_sys->archived_lsn = log_sys->lsn;
801
log_sys->next_archived_lsn = 0;
806
log_sys->next_archived_lsn = ut_dulint_zero;
803
808
log_sys->n_pending_archive_ios = 0;
823
828
log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE);
825
830
log_sys->buf_free = LOG_BLOCK_HDR_SIZE;
826
log_sys->lsn = LOG_START_LSN + LOG_BLOCK_HDR_SIZE;
831
log_sys->lsn = ut_dulint_add(LOG_START_LSN, LOG_BLOCK_HDR_SIZE);
828
833
mutex_exit(&(log_sys->mutex));
835
840
recv_sys->scanned_lsn = log_sys->lsn;
836
841
recv_sys->scanned_checkpoint_no = 0;
837
842
recv_sys->recovered_lsn = log_sys->lsn;
838
recv_sys->limit_lsn = IB_ULONGLONG_MAX;
843
recv_sys->limit_lsn = ut_dulint_max;
842
847
/**********************************************************************
843
848
Inits a log group to the log system. */
1097
1102
log_group_t* group, /* in: log group */
1098
1103
ulint nth_file, /* in: header to the nth file in the
1099
1104
log file space */
1100
ib_uint64_t start_lsn) /* in: log file data starts at this
1105
dulint start_lsn) /* in: log file data starts at this
1109
1114
buf = *(group->file_header_bufs + nth_file);
1111
1116
mach_write_to_4(buf + LOG_GROUP_ID, group->id);
1112
mach_write_ull(buf + LOG_FILE_START_LSN, start_lsn);
1117
mach_write_to_8(buf + LOG_FILE_START_LSN, start_lsn);
1114
1119
/* Wipe over possible label of ibbackup --restore */
1115
1120
memcpy(buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, " ", 4);
1129
1134
srv_os_log_pending_writes++;
1131
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id, 0,
1136
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id,
1132
1137
dest_offset / UNIV_PAGE_SIZE,
1133
1138
dest_offset % UNIV_PAGE_SIZE,
1134
1139
OS_FILE_LOG_BLOCK_SIZE,
1161
1166
byte* buf, /* in: buffer */
1162
1167
ulint len, /* in: buffer len; must be divisible
1163
1168
by OS_FILE_LOG_BLOCK_SIZE */
1164
ib_uint64_t start_lsn, /* in: start lsn of the buffer; must
1169
dulint start_lsn, /* in: start lsn of the buffer; must
1165
1170
be divisible by
1166
1171
OS_FILE_LOG_BLOCK_SIZE */
1167
1172
ulint new_data_offset)/* in: start offset of new data in
1177
1182
ut_ad(mutex_own(&(log_sys->mutex)));
1178
1183
ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0);
1179
ut_a(((ulint) start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
1184
ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
1181
1186
if (new_data_offset == 0) {
1182
1187
write_header = TRUE;
1216
1221
fprintf(stderr,
1217
1222
"Writing log file segment to group %lu"
1218
1223
" offset %lu len %lu\n"
1219
"start lsn %"PRIu64"\n"
1224
"start lsn %lu %lu\n"
1220
1225
"First block n:o %lu last block n:o %lu\n",
1221
1226
(ulong) group->id, (ulong) next_offset,
1222
1227
(ulong) write_len,
1228
(ulong) ut_dulint_get_high(start_lsn),
1229
(ulong) ut_dulint_get_low(start_lsn),
1224
1230
(ulong) log_block_get_hdr_no(buf),
1225
1231
(ulong) log_block_get_hdr_no(
1226
1232
buf + write_len - OS_FILE_LOG_BLOCK_SIZE));
1248
1254
srv_os_log_pending_writes++;
1250
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id, 0,
1256
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id,
1251
1257
next_offset / UNIV_PAGE_SIZE,
1252
1258
next_offset % UNIV_PAGE_SIZE, write_len, buf, group);
1273
1279
that the log has been written to the log file up to the last log entry written
1274
1280
by the transaction. If there is a flush running, it waits and checks if the
1275
1281
flush flushed enough. If not, starts a new flush. */
1278
1284
log_write_up_to(
1279
1285
/*============*/
1280
ib_uint64_t lsn, /* in: log sequence number up to which
1281
the log should be written,
1282
IB_ULONGLONG_MAX if not specified */
1283
ulint wait, /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
1284
or LOG_WAIT_ALL_GROUPS */
1285
ibool flush_to_disk)
1286
/* in: TRUE if we want the written log
1287
also to be flushed to disk */
1286
dulint lsn, /* in: log sequence number up to which the log should
1287
be written, ut_dulint_max if not specified */
1288
ulint wait, /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
1289
or LOG_WAIT_ALL_GROUPS */
1290
ibool flush_to_disk)
1291
/* in: TRUE if we want the written log also to be
1289
1294
log_group_t* group;
1290
1295
ulint start_offset;
1329
1334
if (!flush_to_disk
1330
&& (log_sys->written_to_all_lsn >= lsn
1331
|| (log_sys->written_to_some_lsn >= lsn
1335
&& (ut_dulint_cmp(log_sys->written_to_all_lsn, lsn) >= 0
1336
|| (ut_dulint_cmp(log_sys->written_to_some_lsn, lsn)
1332
1338
&& wait != LOG_WAIT_ALL_GROUPS))) {
1334
1340
mutex_exit(&(log_sys->mutex));
1377
1384
#ifdef UNIV_DEBUG
1378
1385
if (log_debug_writes) {
1379
1386
fprintf(stderr,
1380
"Writing log from %"PRIu64" up to lsn %"PRIu64"\n",
1381
log_sys->written_to_all_lsn,
1387
"Writing log from %lu %lu up to lsn %lu %lu\n",
1388
(ulong) ut_dulint_get_high(
1389
log_sys->written_to_all_lsn),
1390
(ulong) ut_dulint_get_low(
1391
log_sys->written_to_all_lsn),
1392
(ulong) ut_dulint_get_high(log_sys->lsn),
1393
(ulong) ut_dulint_get_low(log_sys->lsn));
1384
1395
#endif /* UNIV_DEBUG */
1385
1396
log_sys->n_pending_writes++;
1431
1442
log_group_write_buf(
1432
1443
group, log_sys->buf + area_start,
1433
1444
area_end - area_start,
1434
ut_uint64_align_down(log_sys->written_to_all_lsn,
1445
ut_dulint_align_down(log_sys->written_to_all_lsn,
1435
1446
OS_FILE_LOG_BLOCK_SIZE),
1436
1447
start_offset - area_start);
1479
1490
mutex_exit(&(log_sys->mutex));
1482
case LOG_WAIT_ONE_GROUP:
1492
if (wait == LOG_WAIT_ONE_GROUP) {
1483
1493
os_event_wait(log_sys->one_flushed_event);
1485
case LOG_WAIT_ALL_GROUPS:
1494
} else if (wait == LOG_WAIT_ALL_GROUPS) {
1486
1495
os_event_wait(log_sys->no_flush_event);
1493
#endif /* UNIV_DEBUG */
1497
ut_ad(wait == LOG_NO_WAIT);
1497
1501
/********************************************************************
1498
1502
Does a syncronous flush of the log buffer to disk. */
1501
1505
log_buffer_flush_to_disk(void)
1502
1506
/*==========================*/
1506
1510
mutex_enter(&(log_sys->mutex));
1546
1552
Advances the smallest lsn for which there are unflushed dirty blocks in the
1547
1553
buffer pool. NOTE: this function may only be called if the calling thread owns
1548
1554
no synchronization objects! */
1551
1557
log_preflush_pool_modified_pages(
1552
1558
/*=============================*/
1553
/* out: FALSE if there was a
1554
flush batch of the same type
1555
running, which means that we
1556
could not start this flush
1558
ib_uint64_t new_oldest, /* in: try to advance
1559
oldest_modified_lsn at least
1561
ibool sync) /* in: TRUE if synchronous
1562
operation is desired */
1559
/* out: FALSE if there was a flush batch of
1560
the same type running, which means that we
1561
could not start this flush batch */
1562
dulint new_oldest, /* in: try to advance oldest_modified_lsn
1563
at least to this lsn */
1564
ibool sync) /* in: TRUE if synchronous operation is
1600
1603
ut_ad(mutex_own(&(log_sys->mutex)));
1601
1604
ut_ad(log_sys->n_pending_checkpoint_writes == 0);
1603
log_sys->next_checkpoint_no++;
1606
log_sys->next_checkpoint_no
1607
= ut_dulint_add(log_sys->next_checkpoint_no, 1);
1605
1609
log_sys->last_checkpoint_lsn = log_sys->next_checkpoint_lsn;
1676
1680
log_group_t* group2;
1677
1681
#ifdef UNIV_LOG_ARCHIVE
1678
ib_uint64_t archived_lsn;
1679
ib_uint64_t next_archived_lsn;
1682
dulint archived_lsn;
1683
dulint next_archived_lsn;
1680
1684
#endif /* UNIV_LOG_ARCHIVE */
1686
1690
ut_ad(mutex_own(&(log_sys->mutex)));
1687
1691
#if LOG_CHECKPOINT_SIZE > OS_FILE_LOG_BLOCK_SIZE
1691
1695
buf = group->checkpoint_buf;
1693
mach_write_ull(buf + LOG_CHECKPOINT_NO, log_sys->next_checkpoint_no);
1694
mach_write_ull(buf + LOG_CHECKPOINT_LSN, log_sys->next_checkpoint_lsn);
1697
mach_write_to_8(buf + LOG_CHECKPOINT_NO, log_sys->next_checkpoint_no);
1698
mach_write_to_8(buf + LOG_CHECKPOINT_LSN,
1699
log_sys->next_checkpoint_lsn);
1696
1701
mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET,
1697
1702
log_group_calc_lsn_offset(
1702
1707
#ifdef UNIV_LOG_ARCHIVE
1703
1708
if (log_sys->archiving_state == LOG_ARCH_OFF) {
1704
archived_lsn = IB_ULONGLONG_MAX;
1709
archived_lsn = ut_dulint_max;
1706
1711
archived_lsn = log_sys->archived_lsn;
1708
if (archived_lsn != log_sys->next_archived_lsn) {
1713
if (0 != ut_dulint_cmp(archived_lsn,
1714
log_sys->next_archived_lsn)) {
1709
1715
next_archived_lsn = log_sys->next_archived_lsn;
1710
1716
/* For debugging only */
1714
mach_write_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN, archived_lsn);
1720
mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, archived_lsn);
1715
1721
#else /* UNIV_LOG_ARCHIVE */
1716
mach_write_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN, IB_ULONGLONG_MAX);
1722
mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, ut_dulint_max);
1717
1723
#endif /* UNIV_LOG_ARCHIVE */
1719
1725
for (i = 0; i < LOG_MAX_N_GROUPS; i++) {
1754
1760
/* We alternate the physical place of the checkpoint info in the first
1757
if ((log_sys->next_checkpoint_no & 1) == 0) {
1763
if (ut_dulint_get_low(log_sys->next_checkpoint_no) % 2 == 0) {
1758
1764
write_offset = LOG_CHECKPOINT_1;
1760
1766
write_offset = LOG_CHECKPOINT_2;
1775
1781
added with 1, as we want to distinguish between a normal log
1776
1782
file write and a checkpoint field write */
1778
fil_io(OS_FILE_WRITE | OS_FILE_LOG, FALSE, group->space_id, 0,
1784
fil_io(OS_FILE_WRITE | OS_FILE_LOG, FALSE, group->space_id,
1779
1785
write_offset / UNIV_PAGE_SIZE,
1780
1786
write_offset % UNIV_PAGE_SIZE,
1781
1787
OS_FILE_LOG_BLOCK_SIZE,
1788
1794
/**********************************************************
1789
1795
Writes info to a buffer of a log group when log files are created in
1790
1796
backup restoration. */
1793
1799
log_reset_first_header_and_checkpoint(
1794
1800
/*==================================*/
1795
byte* hdr_buf,/* in: buffer which will be written to the
1796
start of the first log file */
1797
ib_uint64_t start) /* in: lsn of the start of the first log file;
1798
we pretend that there is a checkpoint at
1799
start + LOG_BLOCK_HDR_SIZE */
1801
byte* hdr_buf,/* in: buffer which will be written to the start
1802
of the first log file */
1803
dulint start) /* in: lsn of the start of the first log file;
1804
we pretend that there is a checkpoint at
1805
start + LOG_BLOCK_HDR_SIZE */
1805
1811
mach_write_to_4(hdr_buf + LOG_GROUP_ID, 0);
1806
mach_write_ull(hdr_buf + LOG_FILE_START_LSN, start);
1812
mach_write_to_8(hdr_buf + LOG_FILE_START_LSN, start);
1808
lsn = start + LOG_BLOCK_HDR_SIZE;
1814
lsn = ut_dulint_add(start, LOG_BLOCK_HDR_SIZE);
1810
1816
/* Write the label of ibbackup --restore */
1811
1817
strcpy((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
1815
1821
+ (sizeof "ibbackup ") - 1));
1816
1822
buf = hdr_buf + LOG_CHECKPOINT_1;
1818
mach_write_ull(buf + LOG_CHECKPOINT_NO, 0);
1819
mach_write_ull(buf + LOG_CHECKPOINT_LSN, lsn);
1824
mach_write_to_8(buf + LOG_CHECKPOINT_NO, ut_dulint_zero);
1825
mach_write_to_8(buf + LOG_CHECKPOINT_LSN, lsn);
1821
1827
mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET,
1822
1828
LOG_FILE_HDR_SIZE + LOG_BLOCK_HDR_SIZE);
1824
1830
mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, 2 * 1024 * 1024);
1826
mach_write_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN, IB_ULONGLONG_MAX);
1832
mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, ut_dulint_max);
1828
1834
fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1);
1829
1835
mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_1, fold);
1851
1857
log_sys->n_log_ios++;
1853
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, group->space_id, 0,
1859
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE, group->space_id,
1854
1860
field / UNIV_PAGE_SIZE, field % UNIV_PAGE_SIZE,
1855
1861
OS_FILE_LOG_BLOCK_SIZE, log_sys->checkpoint_buf, NULL);
1858
1864
/**********************************************************
1859
1865
Writes checkpoint info to groups. */
1862
1868
log_groups_write_checkpoint_info(void)
1863
1869
/*==================================*/
1924
1930
mutex_enter(&(log_sys->mutex));
1926
1932
if (!write_always
1927
&& log_sys->last_checkpoint_lsn >= oldest_lsn) {
1933
&& ut_dulint_cmp(log_sys->last_checkpoint_lsn, oldest_lsn) >= 0) {
1929
1935
mutex_exit(&(log_sys->mutex));
1934
ut_ad(log_sys->written_to_all_lsn >= oldest_lsn);
1940
ut_ad(ut_dulint_cmp(log_sys->written_to_all_lsn, oldest_lsn) >= 0);
1936
1942
if (log_sys->n_pending_checkpoint_writes > 0) {
1937
1943
/* A checkpoint write is running */
1952
1958
#ifdef UNIV_DEBUG
1953
1959
if (log_debug_writes) {
1954
fprintf(stderr, "Making checkpoint no %lu at lsn %"PRIu64"\n",
1955
(ulong) log_sys->next_checkpoint_no,
1960
fprintf(stderr, "Making checkpoint no %lu at lsn %lu %lu\n",
1961
(ulong) ut_dulint_get_low(log_sys->next_checkpoint_no),
1962
(ulong) ut_dulint_get_high(oldest_lsn),
1963
(ulong) ut_dulint_get_low(oldest_lsn));
1958
1965
#endif /* UNIV_DEBUG */
1973
1980
/********************************************************************
1974
1981
Makes a checkpoint at a given lsn or later. */
1977
1984
log_make_checkpoint_at(
1978
1985
/*===================*/
1979
ib_uint64_t lsn, /* in: make a checkpoint at this or a
1980
later lsn, if IB_ULONGLONG_MAX, makes
1981
a checkpoint at the latest lsn */
1982
ibool write_always) /* in: the function normally checks if
1983
the the new checkpoint would have a
1984
greater lsn than the previous one: if
1985
not, then no physical write is done;
1986
by setting this parameter TRUE, a
1987
physical write will always be made to
1986
dulint lsn, /* in: make a checkpoint at this or a later
1987
lsn, if ut_dulint_max, makes a checkpoint at
1989
ibool write_always) /* in: the function normally checks if the
1990
the new checkpoint would have a greater
1991
lsn than the previous one: if not, then no
1992
physical write is done; by setting this
1993
parameter TRUE, a physical write will always be
1994
made to log files */
1990
1998
/* Preflush pages synchronously */
1992
while (!log_preflush_pool_modified_pages(lsn, TRUE));
1994
while (!log_checkpoint(TRUE, write_always));
2003
success = log_preflush_pool_modified_pages(lsn, TRUE);
2009
success = log_checkpoint(TRUE, write_always);
1997
2013
/********************************************************************
2047
checkpoint_age = log->lsn - log->last_checkpoint_lsn;
2063
checkpoint_age = ut_dulint_minus(log->lsn, log->last_checkpoint_lsn);
2049
2065
if (checkpoint_age > log->max_checkpoint_age) {
2050
2066
/* A checkpoint is urgent: we do it synchronously */
2066
2082
mutex_exit(&(log->mutex));
2069
ib_uint64_t new_oldest = oldest_lsn + advance;
2085
dulint new_oldest = ut_dulint_add(oldest_lsn, advance);
2071
2087
success = log_preflush_pool_modified_pages(new_oldest, sync);
2099
2115
/**********************************************************
2100
2116
Reads a specified log segment to a buffer. */
2103
2119
log_group_read_log_seg(
2104
2120
/*===================*/
2105
2121
ulint type, /* in: LOG_ARCHIVE or LOG_RECOVER */
2106
2122
byte* buf, /* in: buffer where to read */
2107
2123
log_group_t* group, /* in: log group */
2108
ib_uint64_t start_lsn, /* in: read area start */
2109
ib_uint64_t end_lsn) /* in: read area end */
2124
dulint start_lsn, /* in: read area start */
2125
dulint end_lsn) /* in: read area end */
2112
2128
ulint source_offset;
2115
2131
ut_ad(mutex_own(&(log_sys->mutex)));
2117
sync = (type == LOG_RECOVER);
2135
if (type == LOG_RECOVER) {
2119
2139
source_offset = log_group_calc_lsn_offset(start_lsn, group);
2121
len = (ulint) (end_lsn - start_lsn);
2141
len = ut_dulint_minus(end_lsn, start_lsn);
2123
2143
ut_ad(len != 0);
2137
2157
log_sys->n_log_ios++;
2139
fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id, 0,
2159
fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id,
2140
2160
source_offset / UNIV_PAGE_SIZE, source_offset % UNIV_PAGE_SIZE,
2141
2161
len, buf, NULL);
2163
start_lsn = ut_dulint_add(start_lsn, len);
2146
if (start_lsn != end_lsn) {
2166
if (ut_dulint_cmp(start_lsn, end_lsn) != 0) {
2175
2195
ulint nth_file, /* in: header to the nth file in the
2176
2196
archive log file space */
2177
2197
ulint file_no, /* in: archived file number */
2178
ib_uint64_t start_lsn) /* in: log file data starts at this
2198
dulint start_lsn) /* in: log file data starts at this
2188
2208
buf = *(group->archive_file_header_bufs + nth_file);
2190
2210
mach_write_to_4(buf + LOG_GROUP_ID, group->id);
2191
mach_write_ull(buf + LOG_FILE_START_LSN, start_lsn);
2211
mach_write_to_8(buf + LOG_FILE_START_LSN, start_lsn);
2192
2212
mach_write_to_4(buf + LOG_FILE_NO, file_no);
2194
2214
mach_write_to_4(buf + LOG_FILE_ARCH_COMPLETED, FALSE);
2213
2233
log_group_t* group, /* in: log group */
2214
2234
ulint nth_file, /* in: header to the nth file in the
2215
2235
archive log file space */
2216
ib_uint64_t end_lsn) /* in: end lsn of the file */
2236
dulint end_lsn) /* in: end lsn of the file */
2219
2239
ulint dest_offset;
2224
2244
buf = *(group->archive_file_header_bufs + nth_file);
2226
2246
mach_write_to_4(buf + LOG_FILE_ARCH_COMPLETED, TRUE);
2227
mach_write_ull(buf + LOG_FILE_END_LSN, end_lsn);
2247
mach_write_to_8(buf + LOG_FILE_END_LSN, end_lsn);
2229
2249
dest_offset = nth_file * group->file_size + LOG_FILE_ARCH_COMPLETED;
2246
2266
/*==============*/
2247
2267
log_group_t* group) /* in: log group */
2249
os_file_t file_handle;
2250
ib_uint64_t start_lsn;
2251
ib_uint64_t end_lsn;
2269
os_file_t file_handle;
2260
2280
ut_ad(mutex_own(&(log_sys->mutex)));
2262
2282
start_lsn = log_sys->archived_lsn;
2264
ut_a(start_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
2284
ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
2266
2286
end_lsn = log_sys->next_archived_lsn;
2268
ut_a(end_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
2288
ut_a(ut_dulint_get_low(end_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
2270
2290
buf = log_sys->archive_buf;
2344
2364
#ifdef UNIV_DEBUG
2345
2365
if (log_debug_writes) {
2346
2366
fprintf(stderr,
2347
"Archiving starting at lsn %"PRIu64", len %lu"
2367
"Archiving starting at lsn %lu %lu, len %lu"
2348
2368
" to group %lu\n",
2369
(ulong) ut_dulint_get_high(start_lsn),
2370
(ulong) ut_dulint_get_low(start_lsn),
2350
2371
(ulong) len, (ulong) group->id);
2352
2373
#endif /* UNIV_DEBUG */
2445
2466
#endif /* UNIV_DEBUG */
2447
2468
/* Calculate the archive file space start lsn */
2448
start_lsn = log_sys->next_archived_lsn
2449
- (end_offset - LOG_FILE_HDR_SIZE + trunc_files
2450
* (group->file_size - LOG_FILE_HDR_SIZE));
2469
start_lsn = ut_dulint_subtract(
2470
log_sys->next_archived_lsn,
2471
end_offset - LOG_FILE_HDR_SIZE + trunc_files
2472
* (group->file_size - LOG_FILE_HDR_SIZE));
2451
2473
end_lsn = start_lsn;
2453
2475
for (i = 0; i < trunc_files; i++) {
2455
end_lsn += group->file_size - LOG_FILE_HDR_SIZE;
2477
end_lsn = ut_dulint_add(end_lsn,
2478
group->file_size - LOG_FILE_HDR_SIZE);
2457
2480
/* Write a notice to the headers of archived log
2458
2481
files that the file write has been completed */
2546
2569
ulint* n_bytes)/* out: archive log buffer size, 0 if nothing to
2549
ibool calc_new_limit;
2550
ib_uint64_t start_lsn;
2551
ib_uint64_t limit_lsn;
2572
ibool calc_new_limit;
2553
2576
calc_new_limit = TRUE;
2555
2578
mutex_enter(&(log_sys->mutex));
2557
switch (log_sys->archiving_state) {
2580
if (log_sys->archiving_state == LOG_ARCH_OFF) {
2560
2581
mutex_exit(&(log_sys->mutex));
2565
case LOG_ARCH_STOPPED:
2566
case LOG_ARCH_STOPPING2:
2587
} else if (log_sys->archiving_state == LOG_ARCH_STOPPED
2588
|| log_sys->archiving_state == LOG_ARCH_STOPPING2) {
2567
2590
mutex_exit(&(log_sys->mutex));
2569
2592
os_event_wait(log_sys->archiving_on);
2594
mutex_enter(&(log_sys->mutex));
2576
2601
if (calc_new_limit) {
2577
2602
ut_a(log_sys->archive_buf_size % OS_FILE_LOG_BLOCK_SIZE == 0);
2578
limit_lsn = start_lsn + log_sys->archive_buf_size;
2603
limit_lsn = ut_dulint_add(start_lsn,
2604
log_sys->archive_buf_size);
2580
2606
*n_bytes = log_sys->archive_buf_size;
2582
if (limit_lsn >= log_sys->lsn) {
2608
if (ut_dulint_cmp(limit_lsn, log_sys->lsn) >= 0) {
2584
limit_lsn = ut_uint64_align_down(
2610
limit_lsn = ut_dulint_align_down(
2585
2611
log_sys->lsn, OS_FILE_LOG_BLOCK_SIZE);
2589
if (log_sys->archived_lsn >= limit_lsn) {
2615
if (ut_dulint_cmp(log_sys->archived_lsn, limit_lsn) >= 0) {
2617
mutex_exit(&(log_sys->mutex));
2594
if (log_sys->written_to_all_lsn < limit_lsn) {
2624
if (ut_dulint_cmp(log_sys->written_to_all_lsn, limit_lsn) < 0) {
2596
2626
mutex_exit(&(log_sys->mutex));
2626
2656
#ifdef UNIV_DEBUG
2627
2657
if (log_debug_writes) {
2628
2658
fprintf(stderr,
2629
"Archiving from lsn %"PRIu64" to lsn %"PRIu64"\n",
2630
log_sys->archived_lsn, limit_lsn);
2659
"Archiving from lsn %lu %lu to lsn %lu %lu\n",
2660
(ulong) ut_dulint_get_high(log_sys->archived_lsn),
2661
(ulong) ut_dulint_get_low(log_sys->archived_lsn),
2662
(ulong) ut_dulint_get_high(limit_lsn),
2663
(ulong) ut_dulint_get_low(limit_lsn));
2632
2665
#endif /* UNIV_DEBUG */
2747
2780
called, and stops the archiving. When archiving is started again, the archived
2748
2781
log file numbers start from 2 higher, so that the archiving will not write
2749
2782
again to the archived log files which exist when this function returns. */
2752
2785
log_archive_stop(void)
2753
2786
/*==================*/
2882
2915
log_sys->archiving_state = LOG_ARCH_ON;
2884
2917
log_sys->archived_lsn
2885
= ut_uint64_align_down(log_sys->lsn,
2918
= ut_dulint_align_down(log_sys->lsn,
2886
2919
OS_FILE_LOG_BLOCK_SIZE);
2887
2920
mutex_exit(&(log_sys->mutex));
2985
3018
data file in the database, so that we know that the file spaces contain
2986
3019
all modifications up to that lsn. This can only be called at database
2987
3020
shutdown. This function also writes all log in log files to the log archive. */
2990
3023
logs_empty_and_mark_files_at_shutdown(void)
2991
3024
/*=======================================*/
2996
3029
if (srv_print_verbose_log) {
2997
3030
ut_print_timestamp(stderr);
3080
3113
log_archive_all();
3081
3114
#endif /* UNIV_LOG_ARCHIVE */
3083
log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
3116
log_make_checkpoint_at(ut_dulint_max, TRUE);
3085
3118
mutex_enter(&(log_sys->mutex));
3087
3120
lsn = log_sys->lsn;
3089
if (lsn != log_sys->last_checkpoint_lsn
3122
if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0)
3090
3123
#ifdef UNIV_LOG_ARCHIVE
3091
3124
|| (srv_log_archive_on
3092
&& lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE)
3125
&& ut_dulint_cmp(lsn,
3126
ut_dulint_add(log_sys->archived_lsn,
3127
LOG_BLOCK_HDR_SIZE))
3093
3129
#endif /* UNIV_LOG_ARCHIVE */
3144
3180
/* Make some checks that the server really is quiet */
3145
3181
ut_a(srv_n_threads_active[SRV_MASTER] == 0);
3146
3182
ut_a(buf_all_freed());
3147
ut_a(lsn == log_sys->lsn);
3183
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
3149
if (lsn < srv_start_lsn) {
3185
if (ut_dulint_cmp(lsn, srv_start_lsn) < 0) {
3150
3186
fprintf(stderr,
3151
3187
"InnoDB: Error: log sequence number"
3152
" at shutdown %"PRIu64"\n"
3153
"InnoDB: is lower than at startup %"PRIu64"!\n",
3154
lsn, srv_start_lsn);
3188
" at shutdown %lu %lu\n"
3189
"InnoDB: is lower than at startup %lu %lu!\n",
3190
(ulong) ut_dulint_get_high(lsn),
3191
(ulong) ut_dulint_get_low(lsn),
3192
(ulong) ut_dulint_get_high(srv_start_lsn),
3193
(ulong) ut_dulint_get_low(srv_start_lsn));
3157
3196
srv_shutdown_lsn = lsn;
3165
3204
/* Make some checks that the server really is quiet */
3166
3205
ut_a(srv_n_threads_active[SRV_MASTER] == 0);
3167
3206
ut_a(buf_all_freed());
3168
ut_a(lsn == log_sys->lsn);
3207
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
3171
3210
/**********************************************************
3172
3211
Checks by parsing that the catenated log segment for a single mtr is
3176
3215
log_check_log_recs(
3177
3216
/*===============*/
3178
byte* buf, /* in: pointer to the start of
3179
the log segment in the
3180
log_sys->buf log buffer */
3181
ulint len, /* in: segment length in bytes */
3182
ib_uint64_t buf_start_lsn) /* in: buffer start lsn */
3217
byte* buf, /* in: pointer to the start of the log segment
3218
in the log_sys->buf log buffer */
3219
ulint len, /* in: segment length in bytes */
3220
dulint buf_start_lsn) /* in: buffer start lsn */
3184
ib_uint64_t contiguous_lsn;
3185
ib_uint64_t scanned_lsn;
3222
dulint contiguous_lsn;
3191
3229
ut_ad(mutex_own(&(log_sys->mutex)));
3204
3242
ut_memcpy(scan_buf, start, end - start);
3206
3244
recv_scan_log_recs(TRUE,
3207
(buf_pool->curr_size
3208
3246
- recv_n_pool_free_frames) * UNIV_PAGE_SIZE,
3209
3247
FALSE, scan_buf, end - start,
3210
ut_uint64_align_down(buf_start_lsn,
3248
ut_dulint_align_down(buf_start_lsn,
3211
3249
OS_FILE_LOG_BLOCK_SIZE),
3212
3250
&contiguous_lsn, &scanned_lsn);
3214
ut_a(scanned_lsn == buf_start_lsn + len);
3215
ut_a(recv_sys->recovered_lsn == scanned_lsn);
3252
ut_a(ut_dulint_cmp(scanned_lsn, ut_dulint_add(buf_start_lsn, len))
3254
ut_a(ut_dulint_cmp(recv_sys->recovered_lsn, scanned_lsn) == 0);
3217
3256
mem_free(buf1);
3222
3261
/**********************************************************
3223
3262
Peeks the current lsn. */
3228
/* out: TRUE if success, FALSE if
3229
could not get the log system mutex */
3230
ib_uint64_t* lsn) /* out: if returns TRUE, current lsn is here */
3267
/* out: TRUE if success, FALSE if could not get the
3269
dulint* lsn) /* out: if returns TRUE, current lsn is here */
3232
3271
if (0 == mutex_enter_nowait(&(log_sys->mutex))) {
3233
3272
*lsn = log_sys->lsn;
3254
3293
mutex_enter(&(log_sys->mutex));
3257
"Log sequence number %"PRIu64"\n"
3258
"Log flushed up to %"PRIu64"\n"
3259
"Last checkpoint at %"PRIu64"\n",
3261
log_sys->flushed_to_disk_lsn,
3262
log_sys->last_checkpoint_lsn);
3296
"Log sequence number %lu %lu\n"
3297
"Log flushed up to %lu %lu\n"
3298
"Last checkpoint at %lu %lu\n",
3299
(ulong) ut_dulint_get_high(log_sys->lsn),
3300
(ulong) ut_dulint_get_low(log_sys->lsn),
3301
(ulong) ut_dulint_get_high(log_sys->flushed_to_disk_lsn),
3302
(ulong) ut_dulint_get_low(log_sys->flushed_to_disk_lsn),
3303
(ulong) ut_dulint_get_high(log_sys->last_checkpoint_lsn),
3304
(ulong) ut_dulint_get_low(log_sys->last_checkpoint_lsn));
3264
3306
current_time = time(NULL);