1
/******************************************************
6
Created 12/9/1995 Heikki Tuuri
7
*******************************************************/
10
#include "mach0data.h"
13
/**********************************************************
14
Checks by parsing that the catenated log segment for a single mtr is
20
byte* buf, /* in: pointer to the start of the log segment
21
in the log_sys->buf log buffer */
22
ulint len, /* in: segment length in bytes */
23
dulint buf_start_lsn); /* in: buffer start lsn */
25
/****************************************************************
26
Gets a log block flush bit. */
29
log_block_get_flush_bit(
30
/*====================*/
31
/* out: TRUE if this block was the first
32
to be written in a log flush */
33
byte* log_block) /* in: log block */
35
if (LOG_BLOCK_FLUSH_BIT_MASK
36
& mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)) {
44
/****************************************************************
45
Sets the log block flush bit. */
48
log_block_set_flush_bit(
49
/*====================*/
50
byte* log_block, /* in: log block */
51
ibool val) /* in: value to set */
55
field = mach_read_from_4(log_block + LOG_BLOCK_HDR_NO);
58
field = field | LOG_BLOCK_FLUSH_BIT_MASK;
60
field = field & ~LOG_BLOCK_FLUSH_BIT_MASK;
63
mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, field);
66
/****************************************************************
67
Gets a log block number stored in the header. */
72
/* out: log block number stored in the block
74
byte* log_block) /* in: log block */
76
return(~LOG_BLOCK_FLUSH_BIT_MASK
77
& mach_read_from_4(log_block + LOG_BLOCK_HDR_NO));
80
/****************************************************************
81
Sets the log block number stored in the header; NOTE that this must be set
82
before the flush bit! */
87
byte* log_block, /* in: log block */
88
ulint n) /* in: log block number: must be > 0 and
89
< LOG_BLOCK_FLUSH_BIT_MASK */
92
ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK);
94
mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, n);
97
/****************************************************************
98
Gets a log block data length. */
101
log_block_get_data_len(
102
/*===================*/
103
/* out: log block data length measured as a
104
byte offset from the block start */
105
byte* log_block) /* in: log block */
107
return(mach_read_from_2(log_block + LOG_BLOCK_HDR_DATA_LEN));
110
/****************************************************************
111
Sets the log block data length. */
114
log_block_set_data_len(
115
/*===================*/
116
byte* log_block, /* in: log block */
117
ulint len) /* in: data length */
119
mach_write_to_2(log_block + LOG_BLOCK_HDR_DATA_LEN, len);
122
/****************************************************************
123
Gets a log block first mtr log record group offset. */
126
log_block_get_first_rec_group(
127
/*==========================*/
128
/* out: first mtr log record group byte offset
129
from the block start, 0 if none */
130
byte* log_block) /* in: log block */
132
return(mach_read_from_2(log_block + LOG_BLOCK_FIRST_REC_GROUP));
135
/****************************************************************
136
Sets the log block first mtr log record group offset. */
139
log_block_set_first_rec_group(
140
/*==========================*/
141
byte* log_block, /* in: log block */
142
ulint offset) /* in: offset, 0 if none */
144
mach_write_to_2(log_block + LOG_BLOCK_FIRST_REC_GROUP, offset);
147
/****************************************************************
148
Gets a log block checkpoint number field (4 lowest bytes). */
151
log_block_get_checkpoint_no(
152
/*========================*/
153
/* out: checkpoint no (4 lowest bytes) */
154
byte* log_block) /* in: log block */
156
return(mach_read_from_4(log_block + LOG_BLOCK_CHECKPOINT_NO));
159
/****************************************************************
160
Sets a log block checkpoint number field (4 lowest bytes). */
163
log_block_set_checkpoint_no(
164
/*========================*/
165
byte* log_block, /* in: log block */
166
dulint no) /* in: checkpoint no */
168
mach_write_to_4(log_block + LOG_BLOCK_CHECKPOINT_NO,
169
ut_dulint_get_low(no));
172
/****************************************************************
173
Converts a lsn to a log block number. */
176
log_block_convert_lsn_to_no(
177
/*========================*/
178
/* out: log block number, it is > 0 and <= 1G */
179
dulint lsn) /* in: lsn of a byte within the block */
183
no = ut_dulint_get_low(lsn) / OS_FILE_LOG_BLOCK_SIZE;
184
no += (ut_dulint_get_high(lsn) % OS_FILE_LOG_BLOCK_SIZE)
185
* 2 * (0x80000000UL / OS_FILE_LOG_BLOCK_SIZE);
187
no = no & 0x3FFFFFFFUL;
192
/****************************************************************
193
Calculates the checksum for a log block. */
196
log_block_calc_checksum(
197
/*====================*/
199
byte* block) /* in: log block */
208
for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
209
sum = sum & 0x7FFFFFFFUL;
210
sum += (((ulint)(*(block + i))) << sh) + (ulint)(*(block + i));
220
/****************************************************************
221
Gets a log block checksum field value. */
224
log_block_get_checksum(
225
/*===================*/
227
byte* log_block) /* in: log block */
229
return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE
230
- LOG_BLOCK_CHECKSUM));
233
/****************************************************************
234
Sets a log block checksum field value. */
237
log_block_set_checksum(
238
/*===================*/
239
byte* log_block, /* in: log block */
240
ulint checksum) /* in: checksum */
242
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
243
- LOG_BLOCK_CHECKSUM,
247
/****************************************************************
248
Initializes a log block in the log buffer. */
253
byte* log_block, /* in: pointer to the log buffer */
254
dulint lsn) /* in: lsn within the log block */
258
ut_ad(mutex_own(&(log_sys->mutex)));
260
no = log_block_convert_lsn_to_no(lsn);
262
log_block_set_hdr_no(log_block, no);
264
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
265
log_block_set_first_rec_group(log_block, 0);
268
/****************************************************************
269
Initializes a log block in the log buffer in the old format, where there
270
was no checksum yet. */
273
log_block_init_in_old_format(
274
/*=========================*/
275
byte* log_block, /* in: pointer to the log buffer */
276
dulint lsn) /* in: lsn within the log block */
280
ut_ad(mutex_own(&(log_sys->mutex)));
282
no = log_block_convert_lsn_to_no(lsn);
284
log_block_set_hdr_no(log_block, no);
285
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
286
- LOG_BLOCK_CHECKSUM, no);
287
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
288
log_block_set_first_rec_group(log_block, 0);
291
/****************************************************************
292
Writes to the log the string given. The log must be released with
296
log_reserve_and_write_fast(
297
/*=======================*/
298
/* out: end lsn of the log record, ut_dulint_zero if
300
byte* str, /* in: string */
301
ulint len, /* in: string length */
302
dulint* start_lsn,/* out: start lsn of the log record */
303
ibool* success)/* out: TRUE if success */
305
log_t* log = log_sys;
311
mutex_enter(&(log->mutex));
313
data_len = len + log->buf_free % OS_FILE_LOG_BLOCK_SIZE;
315
if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
317
/* The string does not fit within the current log block
318
or the log block would become full */
322
mutex_exit(&(log->mutex));
324
return(ut_dulint_zero);
327
*start_lsn = log->lsn;
329
ut_memcpy(log->buf + log->buf_free, str, len);
331
log_block_set_data_len(ut_align_down(log->buf + log->buf_free,
332
OS_FILE_LOG_BLOCK_SIZE),
334
#ifdef UNIV_LOG_DEBUG
335
log->old_buf_free = log->buf_free;
336
log->old_lsn = log->lsn;
338
log->buf_free += len;
340
ut_ad(log->buf_free <= log->buf_size);
342
lsn = ut_dulint_add(log->lsn, len);
346
#ifdef UNIV_LOG_DEBUG
347
log_check_log_recs(log->buf + log->old_buf_free,
348
log->buf_free - log->old_buf_free, log->old_lsn);
353
/***************************************************************************
354
Releases the log mutex. */
360
mutex_exit(&(log_sys->mutex));
363
/****************************************************************
364
Gets the current lsn. */
369
/* out: current lsn */
373
mutex_enter(&(log_sys->mutex));
377
mutex_exit(&(log_sys->mutex));
382
/***************************************************************************
383
Checks if there is need for a log buffer flush or a new checkpoint, and does
384
this if yes. Any database operation should call this when it has modified
385
more than about 4 pages. NOTE that this function may only be called when the
386
OS thread owns no synchronization objects except the dictionary mutex. */
392
/* ut_ad(sync_thread_levels_empty()); */
394
if (log_sys->check_flush_or_checkpoint) {