~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/mtr/mtr0mtr.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

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
@file mtr/mtr0mtr.c
 
21
Mini-transaction buffer
 
22
 
 
23
Created 11/26/1995 Heikki Tuuri
 
24
*******************************************************/
 
25
 
 
26
#include "mtr0mtr.h"
 
27
 
 
28
#ifdef UNIV_NONINL
 
29
#include "mtr0mtr.ic"
 
30
#endif
 
31
 
 
32
#include "buf0buf.h"
 
33
#include "page0types.h"
 
34
#include "mtr0log.h"
 
35
#include "log0log.h"
 
36
 
 
37
#ifndef UNIV_HOTBACKUP
 
38
# include "log0recv.h"
 
39
/*****************************************************************//**
 
40
Releases the item in the slot given. */
 
41
UNIV_INLINE
 
42
void
 
43
mtr_memo_slot_release(
 
44
/*==================*/
 
45
        mtr_t*                  mtr,    /*!< in: mtr */
 
46
        mtr_memo_slot_t*        slot)   /*!< in: memo slot */
 
47
{
 
48
        void*   object;
 
49
        ulint   type;
 
50
 
 
51
        ut_ad(mtr && slot);
 
52
 
 
53
        object = slot->object;
 
54
        type = slot->type;
 
55
 
 
56
        if (UNIV_LIKELY(object != NULL)) {
 
57
                if (type <= MTR_MEMO_BUF_FIX) {
 
58
                        buf_page_release((buf_block_t*)object, type, mtr);
 
59
                } else if (type == MTR_MEMO_S_LOCK) {
 
60
                        rw_lock_s_unlock((rw_lock_t*)object);
 
61
#ifdef UNIV_DEBUG
 
62
                } else if (type != MTR_MEMO_X_LOCK) {
 
63
                        ut_ad(type == MTR_MEMO_MODIFY);
 
64
                        ut_ad(mtr_memo_contains(mtr, object,
 
65
                                                MTR_MEMO_PAGE_X_FIX));
 
66
#endif /* UNIV_DEBUG */
 
67
                } else {
 
68
                        rw_lock_x_unlock((rw_lock_t*)object);
 
69
                }
 
70
        }
 
71
 
 
72
        slot->object = NULL;
 
73
}
 
74
 
 
75
/**********************************************************//**
 
76
Releases the mlocks and other objects stored in an mtr memo. They are released
 
77
in the order opposite to which they were pushed to the memo. NOTE! It is
 
78
essential that the x-rw-lock on a modified buffer page is not released before
 
79
buf_page_note_modification is called for that page! Otherwise, some thread
 
80
might race to modify it, and the flush list sort order on lsn would be
 
81
destroyed. */
 
82
UNIV_INLINE
 
83
void
 
84
mtr_memo_pop_all(
 
85
/*=============*/
 
86
        mtr_t*  mtr)    /*!< in: mtr */
 
87
{
 
88
        mtr_memo_slot_t* slot;
 
89
        dyn_array_t*    memo;
 
90
        ulint           offset;
 
91
 
 
92
        ut_ad(mtr);
 
93
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
94
        ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
 
95
                                             commit */
 
96
        memo = &(mtr->memo);
 
97
 
 
98
        offset = dyn_array_get_data_size(memo);
 
99
 
 
100
        while (offset > 0) {
 
101
                offset -= sizeof(mtr_memo_slot_t);
 
102
                slot = dyn_array_get_element(memo, offset);
 
103
 
 
104
                mtr_memo_slot_release(mtr, slot);
 
105
        }
 
106
}
 
107
 
 
108
/************************************************************//**
 
109
Writes the contents of a mini-transaction log, if any, to the database log. */
 
110
static
 
111
void
 
112
mtr_log_reserve_and_write(
 
113
/*======================*/
 
114
        mtr_t*  mtr)    /*!< in: mtr */
 
115
{
 
116
        dyn_array_t*    mlog;
 
117
        dyn_block_t*    block;
 
118
        ulint           data_size;
 
119
        byte*           first_data;
 
120
 
 
121
        ut_ad(mtr);
 
122
 
 
123
        mlog = &(mtr->log);
 
124
 
 
125
        first_data = dyn_block_get_data(mlog);
 
126
 
 
127
        if (mtr->n_log_recs > 1) {
 
128
                mlog_catenate_ulint(mtr, MLOG_MULTI_REC_END, MLOG_1BYTE);
 
129
        } else {
 
130
                *first_data = (byte)((ulint)*first_data
 
131
                                     | MLOG_SINGLE_REC_FLAG);
 
132
        }
 
133
 
 
134
        if (mlog->heap == NULL) {
 
135
                mtr->end_lsn = log_reserve_and_write_fast(
 
136
                        first_data, dyn_block_get_used(mlog),
 
137
                        &mtr->start_lsn);
 
138
                if (mtr->end_lsn) {
 
139
 
 
140
                        return;
 
141
                }
 
142
        }
 
143
 
 
144
        data_size = dyn_array_get_data_size(mlog);
 
145
 
 
146
        /* Open the database log for log_write_low */
 
147
        mtr->start_lsn = log_reserve_and_open(data_size);
 
148
 
 
149
        if (mtr->log_mode == MTR_LOG_ALL) {
 
150
 
 
151
                block = mlog;
 
152
 
 
153
                while (block != NULL) {
 
154
                        log_write_low(dyn_block_get_data(block),
 
155
                                      dyn_block_get_used(block));
 
156
                        block = dyn_array_get_next_block(mlog, block);
 
157
                }
 
158
        } else {
 
159
                ut_ad(mtr->log_mode == MTR_LOG_NONE);
 
160
                /* Do nothing */
 
161
        }
 
162
 
 
163
        mtr->end_lsn = log_close();
 
164
}
 
165
#endif /* !UNIV_HOTBACKUP */
 
166
 
 
167
/***************************************************************//**
 
168
Commits a mini-transaction. */
 
169
UNIV_INTERN
 
170
void
 
171
mtr_commit(
 
172
/*=======*/
 
173
        mtr_t*  mtr)    /*!< in: mini-transaction */
 
174
{
 
175
#ifndef UNIV_HOTBACKUP
 
176
        ibool           write_log;
 
177
#endif /* !UNIV_HOTBACKUP */
 
178
 
 
179
        ut_ad(mtr);
 
180
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
181
        ut_ad(mtr->state == MTR_ACTIVE);
 
182
        ut_d(mtr->state = MTR_COMMITTING);
 
183
 
 
184
#ifndef UNIV_HOTBACKUP
 
185
        /* This is a dirty read, for debugging. */
 
186
        ut_ad(!recv_no_log_write);
 
187
        write_log = mtr->modifications && mtr->n_log_recs;
 
188
 
 
189
        if (write_log) {
 
190
                mtr_log_reserve_and_write(mtr);
 
191
        }
 
192
 
 
193
        /* We first update the modification info to buffer pages, and only
 
194
        after that release the log mutex: this guarantees that when the log
 
195
        mutex is free, all buffer pages contain an up-to-date info of their
 
196
        modifications. This fact is used in making a checkpoint when we look
 
197
        at the oldest modification of any page in the buffer pool. It is also
 
198
        required when we insert modified buffer pages in to the flush list
 
199
        which must be sorted on oldest_modification. */
 
200
 
 
201
        mtr_memo_pop_all(mtr);
 
202
 
 
203
        if (write_log) {
 
204
                log_release();
 
205
        }
 
206
#endif /* !UNIV_HOTBACKUP */
 
207
 
 
208
        ut_d(mtr->state = MTR_COMMITTED);
 
209
        dyn_array_free(&(mtr->memo));
 
210
        dyn_array_free(&(mtr->log));
 
211
}
 
212
 
 
213
#ifndef UNIV_HOTBACKUP
 
214
/**********************************************************//**
 
215
Releases the latches stored in an mtr memo down to a savepoint.
 
216
NOTE! The mtr must not have made changes to buffer pages after the
 
217
savepoint, as these can be handled only by mtr_commit. */
 
218
UNIV_INTERN
 
219
void
 
220
mtr_rollback_to_savepoint(
 
221
/*======================*/
 
222
        mtr_t*  mtr,            /*!< in: mtr */
 
223
        ulint   savepoint)      /*!< in: savepoint */
 
224
{
 
225
        mtr_memo_slot_t* slot;
 
226
        dyn_array_t*    memo;
 
227
        ulint           offset;
 
228
 
 
229
        ut_ad(mtr);
 
230
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
231
        ut_ad(mtr->state == MTR_ACTIVE);
 
232
 
 
233
        memo = &(mtr->memo);
 
234
 
 
235
        offset = dyn_array_get_data_size(memo);
 
236
        ut_ad(offset >= savepoint);
 
237
 
 
238
        while (offset > savepoint) {
 
239
                offset -= sizeof(mtr_memo_slot_t);
 
240
 
 
241
                slot = dyn_array_get_element(memo, offset);
 
242
 
 
243
                ut_ad(slot->type != MTR_MEMO_MODIFY);
 
244
                mtr_memo_slot_release(mtr, slot);
 
245
        }
 
246
}
 
247
 
 
248
/***************************************************//**
 
249
Releases an object in the memo stack. */
 
250
UNIV_INTERN
 
251
void
 
252
mtr_memo_release(
 
253
/*=============*/
 
254
        mtr_t*  mtr,    /*!< in: mtr */
 
255
        void*   object, /*!< in: object */
 
256
        ulint   type)   /*!< in: object type: MTR_MEMO_S_LOCK, ... */
 
257
{
 
258
        mtr_memo_slot_t* slot;
 
259
        dyn_array_t*    memo;
 
260
        ulint           offset;
 
261
 
 
262
        ut_ad(mtr);
 
263
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
264
        ut_ad(mtr->state == MTR_ACTIVE);
 
265
 
 
266
        memo = &(mtr->memo);
 
267
 
 
268
        offset = dyn_array_get_data_size(memo);
 
269
 
 
270
        while (offset > 0) {
 
271
                offset -= sizeof(mtr_memo_slot_t);
 
272
 
 
273
                slot = dyn_array_get_element(memo, offset);
 
274
 
 
275
                if ((object == slot->object) && (type == slot->type)) {
 
276
 
 
277
                        mtr_memo_slot_release(mtr, slot);
 
278
 
 
279
                        break;
 
280
                }
 
281
        }
 
282
}
 
283
#endif /* !UNIV_HOTBACKUP */
 
284
 
 
285
/********************************************************//**
 
286
Reads 1 - 4 bytes from a file page buffered in the buffer pool.
 
287
@return value read */
 
288
UNIV_INTERN
 
289
ulint
 
290
mtr_read_ulint(
 
291
/*===========*/
 
292
        const byte*     ptr,    /*!< in: pointer from where to read */
 
293
        ulint           type,   /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
 
294
        mtr_t*          mtr __attribute__((unused)))
 
295
                                /*!< in: mini-transaction handle */
 
296
{
 
297
        ut_ad(mtr->state == MTR_ACTIVE);
 
298
        ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
 
299
              || mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX));
 
300
        if (type == MLOG_1BYTE) {
 
301
                return(mach_read_from_1(ptr));
 
302
        } else if (type == MLOG_2BYTES) {
 
303
                return(mach_read_from_2(ptr));
 
304
        } else {
 
305
                ut_ad(type == MLOG_4BYTES);
 
306
                return(mach_read_from_4(ptr));
 
307
        }
 
308
}
 
309
 
 
310
/********************************************************//**
 
311
Reads 8 bytes from a file page buffered in the buffer pool.
 
312
@return value read */
 
313
UNIV_INTERN
 
314
dulint
 
315
mtr_read_dulint(
 
316
/*============*/
 
317
        const byte*     ptr,    /*!< in: pointer from where to read */
 
318
        mtr_t*          mtr __attribute__((unused)))
 
319
                                /*!< in: mini-transaction handle */
 
320
{
 
321
        ut_ad(mtr->state == MTR_ACTIVE);
 
322
        ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
 
323
              || mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX));
 
324
        return(mach_read_from_8(ptr));
 
325
}
 
326
 
 
327
#ifdef UNIV_DEBUG
 
328
# ifndef UNIV_HOTBACKUP
 
329
/**********************************************************//**
 
330
Checks if memo contains the given page.
 
331
@return TRUE if contains */
 
332
UNIV_INTERN
 
333
ibool
 
334
mtr_memo_contains_page(
 
335
/*===================*/
 
336
        mtr_t*          mtr,    /*!< in: mtr */
 
337
        const byte*     ptr,    /*!< in: pointer to buffer frame */
 
338
        ulint           type)   /*!< in: type of object */
 
339
{
 
340
        return(mtr_memo_contains(mtr, buf_block_align(ptr), type));
 
341
}
 
342
 
 
343
/*********************************************************//**
 
344
Prints info of an mtr handle. */
 
345
UNIV_INTERN
 
346
void
 
347
mtr_print(
 
348
/*======*/
 
349
        mtr_t*  mtr)    /*!< in: mtr */
 
350
{
 
351
        fprintf(stderr,
 
352
                "Mini-transaction handle: memo size %lu bytes"
 
353
                " log size %lu bytes\n",
 
354
                (ulong) dyn_array_get_data_size(&(mtr->memo)),
 
355
                (ulong) dyn_array_get_data_size(&(mtr->log)));
 
356
}
 
357
# endif /* !UNIV_HOTBACKUP */
 
358
#endif /* UNIV_DEBUG */