~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/mtr/mtr0mtr.c

  • Committer: Stewart Smith
  • Author(s): Marko Mäkelä
  • Date: 2010-12-20 03:21:44 UTC
  • mto: (2021.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 2022.
  • Revision ID: stewart@flamingspork.com-20101220032144-7aqh2z403u7d7bdp
Merge Revision revid:marko.makela@oracle.com-20101104131215-pfxnpidlrzd4krg0 from MySQL InnoDB

Original revid:marko.makela@oracle.com-20101104131215-pfxnpidlrzd4krg0

Original Authors: Marko Mäkelä <marko.makela@oracle.com>
Original commit message:
row_ins_index_entry(): Note that only CREATE INDEX sets foreign=FALSE.

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., 51 Franklin
 
15
St, Fifth Floor, Boston, MA 02110-1301 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 "buf0flu.h"
 
34
#include "page0types.h"
 
35
#include "mtr0log.h"
 
36
#include "log0log.h"
 
37
 
 
38
#ifndef UNIV_HOTBACKUP
 
39
# include "log0recv.h"
 
40
/*****************************************************************//**
 
41
Releases the item in the slot given. */
 
42
static
 
43
void
 
44
mtr_memo_slot_release(
 
45
/*==================*/
 
46
        mtr_t*                  mtr,    /*!< in: mtr */
 
47
        mtr_memo_slot_t*        slot)   /*!< in: memo slot */
 
48
{
 
49
        void*   object;
 
50
        ulint   type;
 
51
 
 
52
        ut_ad(mtr);
 
53
        ut_ad(slot);
 
54
 
 
55
#ifndef UNIV_DEBUG
 
56
        UT_NOT_USED(mtr);
 
57
#endif /* UNIV_DEBUG */
 
58
 
 
59
        object = slot->object;
 
60
        type = slot->type;
 
61
 
 
62
        if (UNIV_LIKELY(object != NULL)) {
 
63
                if (type <= MTR_MEMO_BUF_FIX) {
 
64
                        buf_page_release((buf_block_t*)object, type);
 
65
                } else if (type == MTR_MEMO_S_LOCK) {
 
66
                        rw_lock_s_unlock((rw_lock_t*)object);
 
67
#ifdef UNIV_DEBUG
 
68
                } else if (type != MTR_MEMO_X_LOCK) {
 
69
                        ut_ad(type == MTR_MEMO_MODIFY);
 
70
                        ut_ad(mtr_memo_contains(mtr, object,
 
71
                                                MTR_MEMO_PAGE_X_FIX));
 
72
#endif /* UNIV_DEBUG */
 
73
                } else {
 
74
                        rw_lock_x_unlock((rw_lock_t*)object);
 
75
                }
 
76
        }
 
77
 
 
78
        slot->object = NULL;
 
79
}
 
80
 
 
81
/**********************************************************//**
 
82
Releases the mlocks and other objects stored in an mtr memo.
 
83
They are released in the order opposite to which they were pushed
 
84
to the memo. */
 
85
static
 
86
void
 
87
mtr_memo_pop_all(
 
88
/*=============*/
 
89
        mtr_t*  mtr)    /*!< in: mtr */
 
90
{
 
91
        mtr_memo_slot_t* slot;
 
92
        dyn_array_t*    memo;
 
93
        ulint           offset;
 
94
 
 
95
        ut_ad(mtr);
 
96
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
97
        ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
 
98
                                             commit */
 
99
        memo = &(mtr->memo);
 
100
 
 
101
        offset = dyn_array_get_data_size(memo);
 
102
 
 
103
        while (offset > 0) {
 
104
                offset -= sizeof(mtr_memo_slot_t);
 
105
                slot = dyn_array_get_element(memo, offset);
 
106
 
 
107
                mtr_memo_slot_release(mtr, slot);
 
108
        }
 
109
}
 
110
 
 
111
/*****************************************************************//**
 
112
Releases the item in the slot given. */
 
113
static
 
114
void
 
115
mtr_memo_slot_note_modification(
 
116
/*============================*/
 
117
        mtr_t*                  mtr,    /*!< in: mtr */
 
118
        mtr_memo_slot_t*        slot)   /*!< in: memo slot */
 
119
{
 
120
        ut_ad(mtr);
 
121
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
122
        ut_ad(mtr->modifications);
 
123
 
 
124
        if (slot->object != NULL && slot->type == MTR_MEMO_PAGE_X_FIX) {
 
125
                buf_block_t*    block = (buf_block_t*) slot->object;
 
126
 
 
127
#ifdef UNIV_DEBUG
 
128
                ut_ad(log_flush_order_mutex_own());
 
129
#endif /* UNIV_DEBUG */
 
130
                buf_flush_note_modification(block, mtr);
 
131
        }
 
132
}
 
133
 
 
134
/**********************************************************//**
 
135
Add the modified pages to the buffer flush list. They are released
 
136
in the order opposite to which they were pushed to the memo. NOTE! It is
 
137
essential that the x-rw-lock on a modified buffer page is not released
 
138
before buf_page_note_modification is called for that page! Otherwise,
 
139
some thread might race to modify it, and the flush list sort order on
 
140
lsn would be destroyed. */
 
141
static
 
142
void
 
143
mtr_memo_note_modifications(
 
144
/*========================*/
 
145
        mtr_t*  mtr)    /*!< in: mtr */
 
146
{
 
147
        dyn_array_t*    memo;
 
148
        ulint           offset;
 
149
 
 
150
        ut_ad(mtr);
 
151
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
152
        ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
 
153
                                             commit */
 
154
        memo = &mtr->memo;
 
155
 
 
156
        offset = dyn_array_get_data_size(memo);
 
157
 
 
158
        while (offset > 0) {
 
159
                mtr_memo_slot_t* slot;
 
160
 
 
161
                offset -= sizeof(mtr_memo_slot_t);
 
162
                slot = dyn_array_get_element(memo, offset);
 
163
 
 
164
                mtr_memo_slot_note_modification(mtr, slot);
 
165
        }
 
166
}
 
167
 
 
168
/************************************************************//**
 
169
Writes the contents of a mini-transaction log, if any, to the database log. */
 
170
static
 
171
void
 
172
mtr_log_reserve_and_write(
 
173
/*======================*/
 
174
        mtr_t*  mtr)    /*!< in: mtr */
 
175
{
 
176
        dyn_array_t*    mlog;
 
177
        dyn_block_t*    block;
 
178
        ulint           data_size;
 
179
        byte*           first_data;
 
180
 
 
181
        ut_ad(mtr);
 
182
 
 
183
        mlog = &(mtr->log);
 
184
 
 
185
        first_data = dyn_block_get_data(mlog);
 
186
 
 
187
        if (mtr->n_log_recs > 1) {
 
188
                mlog_catenate_ulint(mtr, MLOG_MULTI_REC_END, MLOG_1BYTE);
 
189
        } else {
 
190
                *first_data = (byte)((ulint)*first_data
 
191
                                     | MLOG_SINGLE_REC_FLAG);
 
192
        }
 
193
 
 
194
        if (mlog->heap == NULL) {
 
195
                mtr->end_lsn = log_reserve_and_write_fast(
 
196
                        first_data, dyn_block_get_used(mlog),
 
197
                        &mtr->start_lsn);
 
198
                if (mtr->end_lsn) {
 
199
 
 
200
                        /* Success. We have the log mutex.
 
201
                        Add pages to flush list and exit */
 
202
                        goto func_exit;
 
203
                }
 
204
        }
 
205
 
 
206
        data_size = dyn_array_get_data_size(mlog);
 
207
 
 
208
        /* Open the database log for log_write_low */
 
209
        mtr->start_lsn = log_reserve_and_open(data_size);
 
210
 
 
211
        if (mtr->log_mode == MTR_LOG_ALL) {
 
212
 
 
213
                block = mlog;
 
214
 
 
215
                while (block != NULL) {
 
216
                        log_write_low(dyn_block_get_data(block),
 
217
                                      dyn_block_get_used(block));
 
218
                        block = dyn_array_get_next_block(mlog, block);
 
219
                }
 
220
        } else {
 
221
                ut_ad(mtr->log_mode == MTR_LOG_NONE);
 
222
                /* Do nothing */
 
223
        }
 
224
 
 
225
        mtr->end_lsn = log_close();
 
226
 
 
227
func_exit:
 
228
        log_flush_order_mutex_enter();
 
229
 
 
230
        /* It is now safe to release the log mutex because the
 
231
        flush_order mutex will ensure that we are the first one
 
232
        to insert into the flush list. */
 
233
        log_release();
 
234
 
 
235
        if (mtr->modifications) {
 
236
                mtr_memo_note_modifications(mtr);
 
237
        }
 
238
 
 
239
        log_flush_order_mutex_exit();
 
240
}
 
241
#endif /* !UNIV_HOTBACKUP */
 
242
 
 
243
/***************************************************************//**
 
244
Commits a mini-transaction. */
 
245
UNIV_INTERN
 
246
void
 
247
mtr_commit(
 
248
/*=======*/
 
249
        mtr_t*  mtr)    /*!< in: mini-transaction */
 
250
{
 
251
        ut_ad(mtr);
 
252
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
253
        ut_ad(mtr->state == MTR_ACTIVE);
 
254
        ut_d(mtr->state = MTR_COMMITTING);
 
255
 
 
256
#ifndef UNIV_HOTBACKUP
 
257
        /* This is a dirty read, for debugging. */
 
258
        ut_ad(!recv_no_log_write);
 
259
 
 
260
        if (mtr->modifications && mtr->n_log_recs) {
 
261
                mtr_log_reserve_and_write(mtr);
 
262
        }
 
263
 
 
264
        mtr_memo_pop_all(mtr);
 
265
#endif /* !UNIV_HOTBACKUP */
 
266
 
 
267
        ut_d(mtr->state = MTR_COMMITTED);
 
268
        dyn_array_free(&(mtr->memo));
 
269
        dyn_array_free(&(mtr->log));
 
270
}
 
271
 
 
272
#ifndef UNIV_HOTBACKUP
 
273
/**********************************************************//**
 
274
Releases the latches stored in an mtr memo down to a savepoint.
 
275
NOTE! The mtr must not have made changes to buffer pages after the
 
276
savepoint, as these can be handled only by mtr_commit. */
 
277
UNIV_INTERN
 
278
void
 
279
mtr_rollback_to_savepoint(
 
280
/*======================*/
 
281
        mtr_t*  mtr,            /*!< in: mtr */
 
282
        ulint   savepoint)      /*!< in: savepoint */
 
283
{
 
284
        mtr_memo_slot_t* slot;
 
285
        dyn_array_t*    memo;
 
286
        ulint           offset;
 
287
 
 
288
        ut_ad(mtr);
 
289
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
290
        ut_ad(mtr->state == MTR_ACTIVE);
 
291
 
 
292
        memo = &(mtr->memo);
 
293
 
 
294
        offset = dyn_array_get_data_size(memo);
 
295
        ut_ad(offset >= savepoint);
 
296
 
 
297
        while (offset > savepoint) {
 
298
                offset -= sizeof(mtr_memo_slot_t);
 
299
 
 
300
                slot = dyn_array_get_element(memo, offset);
 
301
 
 
302
                ut_ad(slot->type != MTR_MEMO_MODIFY);
 
303
 
 
304
                /* We do not call mtr_memo_slot_note_modification()
 
305
                because there MUST be no changes made to the buffer
 
306
                pages after the savepoint */
 
307
                mtr_memo_slot_release(mtr, slot);
 
308
        }
 
309
}
 
310
 
 
311
/***************************************************//**
 
312
Releases an object in the memo stack. */
 
313
UNIV_INTERN
 
314
void
 
315
mtr_memo_release(
 
316
/*=============*/
 
317
        mtr_t*  mtr,    /*!< in: mtr */
 
318
        void*   object, /*!< in: object */
 
319
        ulint   type)   /*!< in: object type: MTR_MEMO_S_LOCK, ... */
 
320
{
 
321
        mtr_memo_slot_t* slot;
 
322
        dyn_array_t*    memo;
 
323
        ulint           offset;
 
324
 
 
325
        ut_ad(mtr);
 
326
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
327
        ut_ad(mtr->state == MTR_ACTIVE);
 
328
 
 
329
        memo = &(mtr->memo);
 
330
 
 
331
        offset = dyn_array_get_data_size(memo);
 
332
 
 
333
        log_flush_order_mutex_enter();
 
334
        while (offset > 0) {
 
335
                offset -= sizeof(mtr_memo_slot_t);
 
336
 
 
337
                slot = dyn_array_get_element(memo, offset);
 
338
 
 
339
                if (object == slot->object && type == slot->type) {
 
340
 
 
341
                        /* We cannot release a page that has been written
 
342
                        to in the middle of a mini-transaction. */
 
343
 
 
344
                        ut_ad(!(mtr->modifications
 
345
                                && slot->type == MTR_MEMO_PAGE_X_FIX));
 
346
 
 
347
                        mtr_memo_slot_release(mtr, slot);
 
348
 
 
349
                        break;
 
350
                }
 
351
        }
 
352
        log_flush_order_mutex_exit();
 
353
}
 
354
#endif /* !UNIV_HOTBACKUP */
 
355
 
 
356
/********************************************************//**
 
357
Reads 1 - 4 bytes from a file page buffered in the buffer pool.
 
358
@return value read */
 
359
UNIV_INTERN
 
360
ulint
 
361
mtr_read_ulint(
 
362
/*===========*/
 
363
        const byte*     ptr,    /*!< in: pointer from where to read */
 
364
        ulint           type,   /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
 
365
        mtr_t*          mtr __attribute__((unused)))
 
366
                                /*!< in: mini-transaction handle */
 
367
{
 
368
        ut_ad(mtr->state == MTR_ACTIVE);
 
369
        ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
 
370
              || mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX));
 
371
        if (type == MLOG_1BYTE) {
 
372
                return(mach_read_from_1(ptr));
 
373
        } else if (type == MLOG_2BYTES) {
 
374
                return(mach_read_from_2(ptr));
 
375
        } else {
 
376
                ut_ad(type == MLOG_4BYTES);
 
377
                return(mach_read_from_4(ptr));
 
378
        }
 
379
}
 
380
 
 
381
#ifdef UNIV_DEBUG
 
382
# ifndef UNIV_HOTBACKUP
 
383
/**********************************************************//**
 
384
Checks if memo contains the given page.
 
385
@return TRUE if contains */
 
386
UNIV_INTERN
 
387
ibool
 
388
mtr_memo_contains_page(
 
389
/*===================*/
 
390
        mtr_t*          mtr,    /*!< in: mtr */
 
391
        const byte*     ptr,    /*!< in: pointer to buffer frame */
 
392
        ulint           type)   /*!< in: type of object */
 
393
{
 
394
        return(mtr_memo_contains(mtr, buf_block_align(ptr), type));
 
395
}
 
396
 
 
397
/*********************************************************//**
 
398
Prints info of an mtr handle. */
 
399
UNIV_INTERN
 
400
void
 
401
mtr_print(
 
402
/*======*/
 
403
        mtr_t*  mtr)    /*!< in: mtr */
 
404
{
 
405
        fprintf(stderr,
 
406
                "Mini-transaction handle: memo size %lu bytes"
 
407
                " log size %lu bytes\n",
 
408
                (ulong) dyn_array_get_data_size(&(mtr->memo)),
 
409
                (ulong) dyn_array_get_data_size(&(mtr->log)));
 
410
}
 
411
# endif /* !UNIV_HOTBACKUP */
 
412
#endif /* UNIV_DEBUG */