~stewart/haildb/trunk

« back to all changes in this revision

Viewing changes to include/log0log.ic

  • Committer: Stewart Smith
  • Date: 2010-04-09 07:57:43 UTC
  • Revision ID: stewart@flamingspork.com-20100409075743-jfh1oml3el1uouvh
Embedded InnoDB 1.0.0 released

2009-04-21      The InnoDB Team

        Embedded InnoDB 1.0.0 released

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
 
4
 
 
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.
 
8
 
 
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.
 
12
 
 
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
 
16
 
 
17
*****************************************************************************/
 
18
 
 
19
/******************************************************
 
20
Database log
 
21
 
 
22
Created 12/9/1995 Heikki Tuuri
 
23
*******************************************************/
 
24
 
 
25
#include "os0file.h"
 
26
#include "mach0data.h"
 
27
#include "mtr0mtr.h"
 
28
 
 
29
/**********************************************************
 
30
Checks by parsing that the catenated log segment for a single mtr is
 
31
consistent. */
 
32
UNIV_INTERN
 
33
ibool
 
34
log_check_log_recs(
 
35
/*===============*/
 
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 */
 
41
 
 
42
/****************************************************************
 
43
Gets a log block flush bit. */
 
44
UNIV_INLINE
 
45
ibool
 
46
log_block_get_flush_bit(
 
47
/*====================*/
 
48
                                        /* out: TRUE if this block was
 
49
                                        the first to be written in a
 
50
                                        log flush */
 
51
        const byte*     log_block)      /* in: log block */
 
52
{
 
53
        if (LOG_BLOCK_FLUSH_BIT_MASK
 
54
            & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)) {
 
55
 
 
56
                return(TRUE);
 
57
        }
 
58
 
 
59
        return(FALSE);
 
60
}
 
61
 
 
62
/****************************************************************
 
63
Sets the log block flush bit. */
 
64
UNIV_INLINE
 
65
void
 
66
log_block_set_flush_bit(
 
67
/*====================*/
 
68
        byte*   log_block,      /* in/out: log block */
 
69
        ibool   val)            /* in: value to set */
 
70
{
 
71
        ulint   field;
 
72
 
 
73
        field = mach_read_from_4(log_block + LOG_BLOCK_HDR_NO);
 
74
 
 
75
        if (val) {
 
76
                field = field | LOG_BLOCK_FLUSH_BIT_MASK;
 
77
        } else {
 
78
                field = field & ~LOG_BLOCK_FLUSH_BIT_MASK;
 
79
        }
 
80
 
 
81
        mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, field);
 
82
}
 
83
 
 
84
/****************************************************************
 
85
Gets a log block number stored in the header. */
 
86
UNIV_INLINE
 
87
ulint
 
88
log_block_get_hdr_no(
 
89
/*=================*/
 
90
                                        /* out: log block number
 
91
                                        stored in the block header */
 
92
        const byte*     log_block)      /* in: log block */
 
93
{
 
94
        return(~LOG_BLOCK_FLUSH_BIT_MASK
 
95
               & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO));
 
96
}
 
97
 
 
98
/****************************************************************
 
99
Sets the log block number stored in the header; NOTE that this must be set
 
100
before the flush bit! */
 
101
UNIV_INLINE
 
102
void
 
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 */
 
108
{
 
109
        ut_ad(n > 0);
 
110
        ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK);
 
111
 
 
112
        mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, n);
 
113
}
 
114
 
 
115
/****************************************************************
 
116
Gets a log block data length. */
 
117
UNIV_INLINE
 
118
ulint
 
119
log_block_get_data_len(
 
120
/*===================*/
 
121
                                        /* out: log block data length
 
122
                                        measured as a byte offset from
 
123
                                        the block start */
 
124
        const byte*     log_block)      /* in: log block */
 
125
{
 
126
        return(mach_read_from_2(log_block + LOG_BLOCK_HDR_DATA_LEN));
 
127
}
 
128
 
 
129
/****************************************************************
 
130
Sets the log block data length. */
 
131
UNIV_INLINE
 
132
void
 
133
log_block_set_data_len(
 
134
/*===================*/
 
135
        byte*   log_block,      /* in/out: log block */
 
136
        ulint   len)            /* in: data length */
 
137
{
 
138
        mach_write_to_2(log_block + LOG_BLOCK_HDR_DATA_LEN, len);
 
139
}
 
140
 
 
141
/****************************************************************
 
142
Gets a log block first mtr log record group offset. */
 
143
UNIV_INLINE
 
144
ulint
 
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 */
 
151
{
 
152
        return(mach_read_from_2(log_block + LOG_BLOCK_FIRST_REC_GROUP));
 
153
}
 
154
 
 
155
/****************************************************************
 
156
Sets the log block first mtr log record group offset. */
 
157
UNIV_INLINE
 
158
void
 
159
log_block_set_first_rec_group(
 
160
/*==========================*/
 
161
        byte*   log_block,      /* in/out: log block */
 
162
        ulint   offset)         /* in: offset, 0 if none */
 
163
{
 
164
        mach_write_to_2(log_block + LOG_BLOCK_FIRST_REC_GROUP, offset);
 
165
}
 
166
 
 
167
/****************************************************************
 
168
Gets a log block checkpoint number field (4 lowest bytes). */
 
169
UNIV_INLINE
 
170
ulint
 
171
log_block_get_checkpoint_no(
 
172
/*========================*/
 
173
                                        /* out: checkpoint no (4
 
174
                                        lowest bytes) */
 
175
        const byte*     log_block)      /* in: log block */
 
176
{
 
177
        return(mach_read_from_4(log_block + LOG_BLOCK_CHECKPOINT_NO));
 
178
}
 
179
 
 
180
/****************************************************************
 
181
Sets a log block checkpoint number field (4 lowest bytes). */
 
182
UNIV_INLINE
 
183
void
 
184
log_block_set_checkpoint_no(
 
185
/*========================*/
 
186
        byte*           log_block,      /* in/out: log block */
 
187
        ib_uint64_t     no)             /* in: checkpoint no */
 
188
{
 
189
        mach_write_to_4(log_block + LOG_BLOCK_CHECKPOINT_NO, (ulint) no);
 
190
}
 
191
 
 
192
/****************************************************************
 
193
Converts a lsn to a log block number. */
 
194
UNIV_INLINE
 
195
ulint
 
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 */
 
201
{
 
202
        return(((ulint) (lsn / OS_FILE_LOG_BLOCK_SIZE) & 0x3FFFFFFFUL) + 1);
 
203
}
 
204
 
 
205
/****************************************************************
 
206
Calculates the checksum for a log block. */
 
207
UNIV_INLINE
 
208
ulint
 
209
log_block_calc_checksum(
 
210
/*====================*/
 
211
                                /* out: checksum */
 
212
        const byte*     block)  /* in: log block */
 
213
{
 
214
        ulint   sum;
 
215
        ulint   sh;
 
216
        ulint   i;
 
217
 
 
218
        sum = 1;
 
219
        sh = 0;
 
220
 
 
221
        for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
 
222
                ulint   b = (ulint) block[i];
 
223
                sum &= 0x7FFFFFFFUL;
 
224
                sum += b;
 
225
                sum += b << sh;
 
226
                sh++;
 
227
                if (sh > 24) {
 
228
                        sh = 0;
 
229
                }
 
230
        }
 
231
 
 
232
        return(sum);
 
233
}
 
234
 
 
235
/****************************************************************
 
236
Gets a log block checksum field value. */
 
237
UNIV_INLINE
 
238
ulint
 
239
log_block_get_checksum(
 
240
/*===================*/
 
241
                                        /* out: checksum */
 
242
        const byte*     log_block)      /* in: log block */
 
243
{
 
244
        return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE
 
245
                                - LOG_BLOCK_CHECKSUM));
 
246
}
 
247
 
 
248
/****************************************************************
 
249
Sets a log block checksum field value. */
 
250
UNIV_INLINE
 
251
void
 
252
log_block_set_checksum(
 
253
/*===================*/
 
254
        byte*   log_block,      /* in/out: log block */
 
255
        ulint   checksum)       /* in: checksum */
 
256
{
 
257
        mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
 
258
                        - LOG_BLOCK_CHECKSUM,
 
259
                        checksum);
 
260
}
 
261
 
 
262
/****************************************************************
 
263
Initializes a log block in the log buffer. */
 
264
UNIV_INLINE
 
265
void
 
266
log_block_init(
 
267
/*===========*/
 
268
        byte*           log_block,      /* in: pointer to the log buffer */
 
269
        ib_uint64_t     lsn)            /* in: lsn within the log block */
 
270
{
 
271
        ulint   no;
 
272
 
 
273
        ut_ad(mutex_own(&(log_sys->mutex)));
 
274
 
 
275
        no = log_block_convert_lsn_to_no(lsn);
 
276
 
 
277
        log_block_set_hdr_no(log_block, no);
 
278
 
 
279
        log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
 
280
        log_block_set_first_rec_group(log_block, 0);
 
281
}
 
282
 
 
283
/****************************************************************
 
284
Initializes a log block in the log buffer in the old format, where there
 
285
was no checksum yet. */
 
286
UNIV_INLINE
 
287
void
 
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 */
 
292
{
 
293
        ulint   no;
 
294
 
 
295
        ut_ad(mutex_own(&(log_sys->mutex)));
 
296
 
 
297
        no = log_block_convert_lsn_to_no(lsn);
 
298
 
 
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);
 
304
}
 
305
 
 
306
#ifndef UNIV_HOTBACKUP
 
307
/****************************************************************
 
308
Writes to the log the string given. The log must be released with
 
309
log_release. */
 
310
UNIV_INLINE
 
311
ib_uint64_t
 
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 */
 
320
{
 
321
        log_t*          log     = log_sys;
 
322
        ulint           data_len;
 
323
        ib_uint64_t     lsn;
 
324
 
 
325
        *success = TRUE;
 
326
 
 
327
        mutex_enter(&(log->mutex));
 
328
 
 
329
        data_len = len + log->buf_free % OS_FILE_LOG_BLOCK_SIZE;
 
330
 
 
331
        if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
 
332
 
 
333
                /* The string does not fit within the current log block
 
334
                or the log block would become full */
 
335
 
 
336
                *success = FALSE;
 
337
 
 
338
                mutex_exit(&(log->mutex));
 
339
 
 
340
                return(0);
 
341
        }
 
342
 
 
343
        *start_lsn = log->lsn;
 
344
 
 
345
        ut_memcpy(log->buf + log->buf_free, str, len);
 
346
 
 
347
        log_block_set_data_len((byte*) ut_align_down(log->buf + log->buf_free,
 
348
                                                     OS_FILE_LOG_BLOCK_SIZE),
 
349
                               data_len);
 
350
#ifdef UNIV_LOG_DEBUG
 
351
        log->old_buf_free = log->buf_free;
 
352
        log->old_lsn = log->lsn;
 
353
#endif
 
354
        log->buf_free += len;
 
355
 
 
356
        ut_ad(log->buf_free <= log->buf_size);
 
357
 
 
358
        lsn = log->lsn += len;
 
359
 
 
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);
 
363
#endif
 
364
        return(lsn);
 
365
}
 
366
 
 
367
/***************************************************************************
 
368
Releases the log mutex. */
 
369
UNIV_INLINE
 
370
void
 
371
log_release(void)
 
372
/*=============*/
 
373
{
 
374
        mutex_exit(&(log_sys->mutex));
 
375
}
 
376
 
 
377
/****************************************************************
 
378
Gets the current lsn. */
 
379
UNIV_INLINE
 
380
ib_uint64_t
 
381
log_get_lsn(void)
 
382
/*=============*/
 
383
                        /* out: current lsn */
 
384
{
 
385
        ib_uint64_t     lsn;
 
386
 
 
387
        mutex_enter(&(log_sys->mutex));
 
388
 
 
389
        lsn = log_sys->lsn;
 
390
 
 
391
        mutex_exit(&(log_sys->mutex));
 
392
 
 
393
        return(lsn);
 
394
}
 
395
 
 
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. */
 
401
UNIV_INLINE
 
402
void
 
403
log_free_check(void)
 
404
/*================*/
 
405
{
 
406
        /* ut_ad(sync_thread_levels_empty()); */
 
407
 
 
408
        if (log_sys->check_flush_or_checkpoint) {
 
409
 
 
410
                log_check_margins();
 
411
        }
 
412
}
 
413
#endif /* !UNIV_HOTBACKUP */