1
/*****************************************************************************
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/******************************************************
22
Created 12/9/1995 Heikki Tuuri
23
*******************************************************/
26
#include "mach0data.h"
29
/**********************************************************
30
Checks by parsing that the catenated log segment for a single mtr is
36
byte* buf, /* in: pointer to the start of
37
the log segment in the
38
log_sys->buf log buffer */
39
ulint len, /* in: segment length in bytes */
40
ib_uint64_t buf_start_lsn); /* in: buffer start lsn */
42
/****************************************************************
43
Gets a log block flush bit. */
46
log_block_get_flush_bit(
47
/*====================*/
48
/* out: TRUE if this block was
49
the first to be written in a
51
const byte* log_block) /* in: log block */
53
if (LOG_BLOCK_FLUSH_BIT_MASK
54
& mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)) {
62
/****************************************************************
63
Sets the log block flush bit. */
66
log_block_set_flush_bit(
67
/*====================*/
68
byte* log_block, /* in/out: log block */
69
ibool val) /* in: value to set */
73
field = mach_read_from_4(log_block + LOG_BLOCK_HDR_NO);
76
field = field | LOG_BLOCK_FLUSH_BIT_MASK;
78
field = field & ~LOG_BLOCK_FLUSH_BIT_MASK;
81
mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, field);
84
/****************************************************************
85
Gets a log block number stored in the header. */
90
/* out: log block number
91
stored in the block header */
92
const byte* log_block) /* in: log block */
94
return(~LOG_BLOCK_FLUSH_BIT_MASK
95
& mach_read_from_4(log_block + LOG_BLOCK_HDR_NO));
98
/****************************************************************
99
Sets the log block number stored in the header; NOTE that this must be set
100
before the flush bit! */
103
log_block_set_hdr_no(
104
/*=================*/
105
byte* log_block, /* in/out: log block */
106
ulint n) /* in: log block number: must be > 0 and
107
< LOG_BLOCK_FLUSH_BIT_MASK */
110
ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK);
112
mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, n);
115
/****************************************************************
116
Gets a log block data length. */
119
log_block_get_data_len(
120
/*===================*/
121
/* out: log block data length
122
measured as a byte offset from
124
const byte* log_block) /* in: log block */
126
return(mach_read_from_2(log_block + LOG_BLOCK_HDR_DATA_LEN));
129
/****************************************************************
130
Sets the log block data length. */
133
log_block_set_data_len(
134
/*===================*/
135
byte* log_block, /* in/out: log block */
136
ulint len) /* in: data length */
138
mach_write_to_2(log_block + LOG_BLOCK_HDR_DATA_LEN, len);
141
/****************************************************************
142
Gets a log block first mtr log record group offset. */
145
log_block_get_first_rec_group(
146
/*==========================*/
147
/* out: first mtr log record
148
group byte offset from the
149
block start, 0 if none */
150
const byte* log_block) /* in: log block */
152
return(mach_read_from_2(log_block + LOG_BLOCK_FIRST_REC_GROUP));
155
/****************************************************************
156
Sets the log block first mtr log record group offset. */
159
log_block_set_first_rec_group(
160
/*==========================*/
161
byte* log_block, /* in/out: log block */
162
ulint offset) /* in: offset, 0 if none */
164
mach_write_to_2(log_block + LOG_BLOCK_FIRST_REC_GROUP, offset);
167
/****************************************************************
168
Gets a log block checkpoint number field (4 lowest bytes). */
171
log_block_get_checkpoint_no(
172
/*========================*/
173
/* out: checkpoint no (4
175
const byte* log_block) /* in: log block */
177
return(mach_read_from_4(log_block + LOG_BLOCK_CHECKPOINT_NO));
180
/****************************************************************
181
Sets a log block checkpoint number field (4 lowest bytes). */
184
log_block_set_checkpoint_no(
185
/*========================*/
186
byte* log_block, /* in/out: log block */
187
ib_uint64_t no) /* in: checkpoint no */
189
mach_write_to_4(log_block + LOG_BLOCK_CHECKPOINT_NO, (ulint) no);
192
/****************************************************************
193
Converts a lsn to a log block number. */
196
log_block_convert_lsn_to_no(
197
/*========================*/
198
/* out: log block number,
199
it is > 0 and <= 1G */
200
ib_uint64_t lsn) /* in: lsn of a byte within the block */
202
return(((ulint) (lsn / OS_FILE_LOG_BLOCK_SIZE) & 0x3FFFFFFFUL) + 1);
205
/****************************************************************
206
Calculates the checksum for a log block. */
209
log_block_calc_checksum(
210
/*====================*/
212
const byte* block) /* in: log block */
221
for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
222
ulint b = (ulint) block[i];
235
/****************************************************************
236
Gets a log block checksum field value. */
239
log_block_get_checksum(
240
/*===================*/
242
const byte* log_block) /* in: log block */
244
return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE
245
- LOG_BLOCK_CHECKSUM));
248
/****************************************************************
249
Sets a log block checksum field value. */
252
log_block_set_checksum(
253
/*===================*/
254
byte* log_block, /* in/out: log block */
255
ulint checksum) /* in: checksum */
257
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
258
- LOG_BLOCK_CHECKSUM,
262
/****************************************************************
263
Initializes a log block in the log buffer. */
268
byte* log_block, /* in: pointer to the log buffer */
269
ib_uint64_t lsn) /* in: lsn within the log block */
273
ut_ad(mutex_own(&(log_sys->mutex)));
275
no = log_block_convert_lsn_to_no(lsn);
277
log_block_set_hdr_no(log_block, no);
279
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
280
log_block_set_first_rec_group(log_block, 0);
283
/****************************************************************
284
Initializes a log block in the log buffer in the old format, where there
285
was no checksum yet. */
288
log_block_init_in_old_format(
289
/*=========================*/
290
byte* log_block, /* in: pointer to the log buffer */
291
ib_uint64_t lsn) /* in: lsn within the log block */
295
ut_ad(mutex_own(&(log_sys->mutex)));
297
no = log_block_convert_lsn_to_no(lsn);
299
log_block_set_hdr_no(log_block, no);
300
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
301
- LOG_BLOCK_CHECKSUM, no);
302
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
303
log_block_set_first_rec_group(log_block, 0);
306
#ifndef UNIV_HOTBACKUP
307
/****************************************************************
308
Writes to the log the string given. The log must be released with
312
log_reserve_and_write_fast(
313
/*=======================*/
314
/* out: end lsn of the log record,
315
zero if did not succeed */
316
byte* str, /* in: string */
317
ulint len, /* in: string length */
318
ib_uint64_t* start_lsn,/* out: start lsn of the log record */
319
ibool* success)/* out: TRUE if success */
321
log_t* log = log_sys;
327
mutex_enter(&(log->mutex));
329
data_len = len + log->buf_free % OS_FILE_LOG_BLOCK_SIZE;
331
if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
333
/* The string does not fit within the current log block
334
or the log block would become full */
338
mutex_exit(&(log->mutex));
343
*start_lsn = log->lsn;
345
ut_memcpy(log->buf + log->buf_free, str, len);
347
log_block_set_data_len((byte*) ut_align_down(log->buf + log->buf_free,
348
OS_FILE_LOG_BLOCK_SIZE),
350
#ifdef UNIV_LOG_DEBUG
351
log->old_buf_free = log->buf_free;
352
log->old_lsn = log->lsn;
354
log->buf_free += len;
356
ut_ad(log->buf_free <= log->buf_size);
358
lsn = log->lsn += len;
360
#ifdef UNIV_LOG_DEBUG
361
log_check_log_recs(log->buf + log->old_buf_free,
362
log->buf_free - log->old_buf_free, log->old_lsn);
367
/***************************************************************************
368
Releases the log mutex. */
374
mutex_exit(&(log_sys->mutex));
377
/****************************************************************
378
Gets the current lsn. */
383
/* out: current lsn */
387
mutex_enter(&(log_sys->mutex));
391
mutex_exit(&(log_sys->mutex));
396
/***************************************************************************
397
Checks if there is need for a log buffer flush or a new checkpoint, and does
398
this if yes. Any database operation should call this when it has modified
399
more than about 4 pages. NOTE that this function may only be called when the
400
OS thread owns no synchronization objects except the dictionary mutex. */
406
/* ut_ad(sync_thread_levels_empty()); */
408
if (log_sys->check_flush_or_checkpoint) {
413
#endif /* !UNIV_HOTBACKUP */