~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/include/log0log.ic

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
Database log
 
3
 
 
4
(c) 1995 Innobase Oy
 
5
 
 
6
Created 12/9/1995 Heikki Tuuri
 
7
*******************************************************/
 
8
 
 
9
#include "os0file.h"
 
10
#include "mach0data.h"
 
11
#include "mtr0mtr.h"
 
12
 
 
13
/**********************************************************
 
14
Checks by parsing that the catenated log segment for a single mtr is
 
15
consistent. */
 
16
 
 
17
ibool
 
18
log_check_log_recs(
 
19
/*===============*/
 
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 */
 
24
 
 
25
/****************************************************************
 
26
Gets a log block flush bit. */
 
27
UNIV_INLINE
 
28
ibool
 
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 */
 
34
{
 
35
        if (LOG_BLOCK_FLUSH_BIT_MASK
 
36
            & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)) {
 
37
 
 
38
                return(TRUE);
 
39
        }
 
40
 
 
41
        return(FALSE);
 
42
}
 
43
 
 
44
/****************************************************************
 
45
Sets the log block flush bit. */
 
46
UNIV_INLINE
 
47
void
 
48
log_block_set_flush_bit(
 
49
/*====================*/
 
50
        byte*   log_block,      /* in: log block */
 
51
        ibool   val)            /* in: value to set */
 
52
{
 
53
        ulint   field;
 
54
 
 
55
        field = mach_read_from_4(log_block + LOG_BLOCK_HDR_NO);
 
56
 
 
57
        if (val) {
 
58
                field = field | LOG_BLOCK_FLUSH_BIT_MASK;
 
59
        } else {
 
60
                field = field & ~LOG_BLOCK_FLUSH_BIT_MASK;
 
61
        }
 
62
 
 
63
        mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, field);
 
64
}
 
65
 
 
66
/****************************************************************
 
67
Gets a log block number stored in the header. */
 
68
UNIV_INLINE
 
69
ulint
 
70
log_block_get_hdr_no(
 
71
/*=================*/
 
72
                                /* out: log block number stored in the block
 
73
                                header */
 
74
        byte*   log_block)      /* in: log block */
 
75
{
 
76
        return(~LOG_BLOCK_FLUSH_BIT_MASK
 
77
               & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO));
 
78
}
 
79
 
 
80
/****************************************************************
 
81
Sets the log block number stored in the header; NOTE that this must be set
 
82
before the flush bit! */
 
83
UNIV_INLINE
 
84
void
 
85
log_block_set_hdr_no(
 
86
/*=================*/
 
87
        byte*   log_block,      /* in: log block */
 
88
        ulint   n)              /* in: log block number: must be > 0 and
 
89
                                < LOG_BLOCK_FLUSH_BIT_MASK */
 
90
{
 
91
        ut_ad(n > 0);
 
92
        ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK);
 
93
 
 
94
        mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, n);
 
95
}
 
96
 
 
97
/****************************************************************
 
98
Gets a log block data length. */
 
99
UNIV_INLINE
 
100
ulint
 
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 */
 
106
{
 
107
        return(mach_read_from_2(log_block + LOG_BLOCK_HDR_DATA_LEN));
 
108
}
 
109
 
 
110
/****************************************************************
 
111
Sets the log block data length. */
 
112
UNIV_INLINE
 
113
void
 
114
log_block_set_data_len(
 
115
/*===================*/
 
116
        byte*   log_block,      /* in: log block */
 
117
        ulint   len)            /* in: data length */
 
118
{
 
119
        mach_write_to_2(log_block + LOG_BLOCK_HDR_DATA_LEN, len);
 
120
}
 
121
 
 
122
/****************************************************************
 
123
Gets a log block first mtr log record group offset. */
 
124
UNIV_INLINE
 
125
ulint
 
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 */
 
131
{
 
132
        return(mach_read_from_2(log_block + LOG_BLOCK_FIRST_REC_GROUP));
 
133
}
 
134
 
 
135
/****************************************************************
 
136
Sets the log block first mtr log record group offset. */
 
137
UNIV_INLINE
 
138
void
 
139
log_block_set_first_rec_group(
 
140
/*==========================*/
 
141
        byte*   log_block,      /* in: log block */
 
142
        ulint   offset)         /* in: offset, 0 if none */
 
143
{
 
144
        mach_write_to_2(log_block + LOG_BLOCK_FIRST_REC_GROUP, offset);
 
145
}
 
146
 
 
147
/****************************************************************
 
148
Gets a log block checkpoint number field (4 lowest bytes). */
 
149
UNIV_INLINE
 
150
ulint
 
151
log_block_get_checkpoint_no(
 
152
/*========================*/
 
153
                                /* out: checkpoint no (4 lowest bytes) */
 
154
        byte*   log_block)      /* in: log block */
 
155
{
 
156
        return(mach_read_from_4(log_block + LOG_BLOCK_CHECKPOINT_NO));
 
157
}
 
158
 
 
159
/****************************************************************
 
160
Sets a log block checkpoint number field (4 lowest bytes). */
 
161
UNIV_INLINE
 
162
void
 
163
log_block_set_checkpoint_no(
 
164
/*========================*/
 
165
        byte*   log_block,      /* in: log block */
 
166
        dulint  no)             /* in: checkpoint no */
 
167
{
 
168
        mach_write_to_4(log_block + LOG_BLOCK_CHECKPOINT_NO,
 
169
                        ut_dulint_get_low(no));
 
170
}
 
171
 
 
172
/****************************************************************
 
173
Converts a lsn to a log block number. */
 
174
UNIV_INLINE
 
175
ulint
 
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 */
 
180
{
 
181
        ulint   no;
 
182
 
 
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);
 
186
 
 
187
        no = no & 0x3FFFFFFFUL;
 
188
 
 
189
        return(no + 1);
 
190
}
 
191
 
 
192
/****************************************************************
 
193
Calculates the checksum for a log block. */
 
194
UNIV_INLINE
 
195
ulint
 
196
log_block_calc_checksum(
 
197
/*====================*/
 
198
                        /* out: checksum */
 
199
        byte*   block)  /* in: log block */
 
200
{
 
201
        ulint   sum;
 
202
        ulint   sh;
 
203
        ulint   i;
 
204
 
 
205
        sum = 1;
 
206
        sh = 0;
 
207
 
 
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));
 
211
                sh++;
 
212
                if (sh > 24) {
 
213
                        sh = 0;
 
214
                }
 
215
        }
 
216
 
 
217
        return(sum);
 
218
}
 
219
 
 
220
/****************************************************************
 
221
Gets a log block checksum field value. */
 
222
UNIV_INLINE
 
223
ulint
 
224
log_block_get_checksum(
 
225
/*===================*/
 
226
                                /* out: checksum */
 
227
        byte*   log_block)      /* in: log block */
 
228
{
 
229
        return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE
 
230
                                - LOG_BLOCK_CHECKSUM));
 
231
}
 
232
 
 
233
/****************************************************************
 
234
Sets a log block checksum field value. */
 
235
UNIV_INLINE
 
236
void
 
237
log_block_set_checksum(
 
238
/*===================*/
 
239
        byte*   log_block,      /* in: log block */
 
240
        ulint   checksum)       /* in: checksum */
 
241
{
 
242
        mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
 
243
                        - LOG_BLOCK_CHECKSUM,
 
244
                        checksum);
 
245
}
 
246
 
 
247
/****************************************************************
 
248
Initializes a log block in the log buffer. */
 
249
UNIV_INLINE
 
250
void
 
251
log_block_init(
 
252
/*===========*/
 
253
        byte*   log_block,      /* in: pointer to the log buffer */
 
254
        dulint  lsn)            /* in: lsn within the log block */
 
255
{
 
256
        ulint   no;
 
257
 
 
258
        ut_ad(mutex_own(&(log_sys->mutex)));
 
259
 
 
260
        no = log_block_convert_lsn_to_no(lsn);
 
261
 
 
262
        log_block_set_hdr_no(log_block, no);
 
263
 
 
264
        log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
 
265
        log_block_set_first_rec_group(log_block, 0);
 
266
}
 
267
 
 
268
/****************************************************************
 
269
Initializes a log block in the log buffer in the old format, where there
 
270
was no checksum yet. */
 
271
UNIV_INLINE
 
272
void
 
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 */
 
277
{
 
278
        ulint   no;
 
279
 
 
280
        ut_ad(mutex_own(&(log_sys->mutex)));
 
281
 
 
282
        no = log_block_convert_lsn_to_no(lsn);
 
283
 
 
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);
 
289
}
 
290
 
 
291
/****************************************************************
 
292
Writes to the log the string given. The log must be released with
 
293
log_release. */
 
294
UNIV_INLINE
 
295
dulint
 
296
log_reserve_and_write_fast(
 
297
/*=======================*/
 
298
                        /* out: end lsn of the log record, ut_dulint_zero if
 
299
                        did not succeed */
 
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 */
 
304
{
 
305
        log_t*  log     = log_sys;
 
306
        ulint   data_len;
 
307
        dulint  lsn;
 
308
 
 
309
        *success = TRUE;
 
310
 
 
311
        mutex_enter(&(log->mutex));
 
312
 
 
313
        data_len = len + log->buf_free % OS_FILE_LOG_BLOCK_SIZE;
 
314
 
 
315
        if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
 
316
 
 
317
                /* The string does not fit within the current log block
 
318
                or the log block would become full */
 
319
 
 
320
                *success = FALSE;
 
321
 
 
322
                mutex_exit(&(log->mutex));
 
323
 
 
324
                return(ut_dulint_zero);
 
325
        }
 
326
 
 
327
        *start_lsn = log->lsn;
 
328
 
 
329
        ut_memcpy(log->buf + log->buf_free, str, len);
 
330
 
 
331
        log_block_set_data_len(ut_align_down(log->buf + log->buf_free,
 
332
                                             OS_FILE_LOG_BLOCK_SIZE),
 
333
                               data_len);
 
334
#ifdef UNIV_LOG_DEBUG
 
335
        log->old_buf_free = log->buf_free;
 
336
        log->old_lsn = log->lsn;
 
337
#endif
 
338
        log->buf_free += len;
 
339
 
 
340
        ut_ad(log->buf_free <= log->buf_size);
 
341
 
 
342
        lsn = ut_dulint_add(log->lsn, len);
 
343
 
 
344
        log->lsn = lsn;
 
345
 
 
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);
 
349
#endif
 
350
        return(lsn);
 
351
}
 
352
 
 
353
/***************************************************************************
 
354
Releases the log mutex. */
 
355
UNIV_INLINE
 
356
void
 
357
log_release(void)
 
358
/*=============*/
 
359
{
 
360
        mutex_exit(&(log_sys->mutex));
 
361
}
 
362
 
 
363
/****************************************************************
 
364
Gets the current lsn. */
 
365
UNIV_INLINE
 
366
dulint
 
367
log_get_lsn(void)
 
368
/*=============*/
 
369
                        /* out: current lsn */
 
370
{
 
371
        dulint  lsn;
 
372
 
 
373
        mutex_enter(&(log_sys->mutex));
 
374
 
 
375
        lsn = log_sys->lsn;
 
376
 
 
377
        mutex_exit(&(log_sys->mutex));
 
378
 
 
379
        return(lsn);
 
380
}
 
381
 
 
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. */
 
387
UNIV_INLINE
 
388
void
 
389
log_free_check(void)
 
390
/*================*/
 
391
{
 
392
        /* ut_ad(sync_thread_levels_empty()); */
 
393
 
 
394
        if (log_sys->check_flush_or_checkpoint) {
 
395
 
 
396
                log_check_margins();
 
397
        }
 
398
}