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., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
1
/******************************************************
21
2
Mini-transaction buffer
23
6
Created 11/26/1995 Heikki Tuuri
24
7
*******************************************************/
32
15
#include "buf0buf.h"
34
16
#include "page0types.h"
35
17
#include "mtr0log.h"
36
18
#include "log0log.h"
38
#ifndef UNIV_HOTBACKUP
39
# include "log0recv.h"
40
/*****************************************************************//**
20
/*********************************************************************
41
21
Releases the item in the slot given. */
44
24
mtr_memo_slot_release(
45
25
/*==================*/
46
mtr_t* mtr, /*!< in: mtr */
47
mtr_memo_slot_t* slot) /*!< in: memo slot */
26
mtr_t* mtr, /* in: mtr */
27
mtr_memo_slot_t* slot) /* in: memo slot */
57
#endif /* UNIV_DEBUG */
59
34
object = slot->object;
62
37
if (UNIV_LIKELY(object != NULL)) {
63
38
if (type <= MTR_MEMO_BUF_FIX) {
64
buf_page_release((buf_block_t*)object, type);
39
buf_page_release((buf_block_t*)object, type, mtr);
65
40
} else if (type == MTR_MEMO_S_LOCK) {
66
41
rw_lock_s_unlock((rw_lock_t*)object);
78
53
slot->object = NULL;
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
56
/**************************************************************
57
Releases the mlocks and other objects stored in an mtr memo. They are released
58
in the order opposite to which they were pushed to the memo. NOTE! It is
59
essential that the x-rw-lock on a modified buffer page is not released before
60
buf_page_note_modification is called for that page! Otherwise, some thread
61
might race to modify it, and the flush list sort order on lsn would be
89
mtr_t* mtr) /*!< in: mtr */
67
mtr_t* mtr) /* in: mtr */
91
69
mtr_memo_slot_t* slot;
103
81
while (offset > 0) {
104
82
offset -= sizeof(mtr_memo_slot_t);
105
slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
83
slot = dyn_array_get_element(memo, offset);
107
85
mtr_memo_slot_release(mtr, slot);
111
/*****************************************************************//**
112
Releases the item in the slot given. */
115
mtr_memo_slot_note_modification(
116
/*============================*/
117
mtr_t* mtr, /*!< in: mtr */
118
mtr_memo_slot_t* slot) /*!< in: memo slot */
121
ut_ad(mtr->magic_n == MTR_MAGIC_N);
122
ut_ad(mtr->modifications);
124
if (slot->object != NULL && slot->type == MTR_MEMO_PAGE_X_FIX) {
125
buf_block_t* block = (buf_block_t*) slot->object;
128
ut_ad(log_flush_order_mutex_own());
129
#endif /* UNIV_DEBUG */
130
buf_flush_note_modification(block, mtr);
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. */
143
mtr_memo_note_modifications(
144
/*========================*/
145
mtr_t* mtr) /*!< in: mtr */
151
ut_ad(mtr->magic_n == MTR_MAGIC_N);
152
ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
156
offset = dyn_array_get_data_size(memo);
159
mtr_memo_slot_t* slot;
161
offset -= sizeof(mtr_memo_slot_t);
162
slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
164
mtr_memo_slot_note_modification(mtr, slot);
168
/************************************************************//**
89
/****************************************************************
169
90
Writes the contents of a mini-transaction log, if any, to the database log. */
172
93
mtr_log_reserve_and_write(
173
94
/*======================*/
174
mtr_t* mtr) /*!< in: mtr */
95
mtr_t* mtr) /* in: mtr */
176
97
dyn_array_t* mlog;
177
98
dyn_block_t* block;
179
101
byte* first_data;
194
116
if (mlog->heap == NULL) {
195
117
mtr->end_lsn = log_reserve_and_write_fast(
196
118
first_data, dyn_block_get_used(mlog),
119
&(mtr->start_lsn), &success);
200
/* Success. We have the log mutex.
201
Add pages to flush list and exit */
225
145
mtr->end_lsn = log_close();
228
log_flush_order_mutex_enter();
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. */
235
if (mtr->modifications) {
236
mtr_memo_note_modifications(mtr);
239
log_flush_order_mutex_exit();
241
#endif /* !UNIV_HOTBACKUP */
243
/***************************************************************//**
148
/*******************************************************************
244
149
Commits a mini-transaction. */
249
mtr_t* mtr) /*!< in: mini-transaction */
154
mtr_t* mtr) /* in: mini-transaction */
252
159
ut_ad(mtr->magic_n == MTR_MAGIC_N);
253
160
ut_ad(mtr->state == MTR_ACTIVE);
254
ut_d(mtr->state = MTR_COMMITTING);
256
#ifndef UNIV_HOTBACKUP
257
/* This is a dirty read, for debugging. */
258
ut_ad(!recv_no_log_write);
260
if (mtr->modifications && mtr->n_log_recs) {
162
mtr->state = MTR_COMMITTING;
164
write_log = mtr->modifications && mtr->n_log_recs;
261
167
mtr_log_reserve_and_write(mtr);
170
/* We first update the modification info to buffer pages, and only
171
after that release the log mutex: this guarantees that when the log
172
mutex is free, all buffer pages contain an up-to-date info of their
173
modifications. This fact is used in making a checkpoint when we look
174
at the oldest modification of any page in the buffer pool. It is also
175
required when we insert modified buffer pages in to the flush list
176
which must be sorted on oldest_modification. */
264
178
mtr_memo_pop_all(mtr);
265
#endif /* !UNIV_HOTBACKUP */
267
ut_d(mtr->state = MTR_COMMITTED);
185
mtr->state = MTR_COMMITTED;
268
187
dyn_array_free(&(mtr->memo));
269
188
dyn_array_free(&(mtr->log));
272
#ifndef UNIV_HOTBACKUP
273
/**********************************************************//**
191
/**************************************************************
274
192
Releases the latches stored in an mtr memo down to a savepoint.
275
193
NOTE! The mtr must not have made changes to buffer pages after the
276
194
savepoint, as these can be handled only by mtr_commit. */
279
197
mtr_rollback_to_savepoint(
280
198
/*======================*/
281
mtr_t* mtr, /*!< in: mtr */
282
ulint savepoint) /*!< in: savepoint */
199
mtr_t* mtr, /* in: mtr */
200
ulint savepoint) /* in: savepoint */
284
202
mtr_memo_slot_t* slot;
285
203
dyn_array_t* memo;
297
215
while (offset > savepoint) {
298
216
offset -= sizeof(mtr_memo_slot_t);
300
slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
218
slot = dyn_array_get_element(memo, offset);
302
220
ut_ad(slot->type != MTR_MEMO_MODIFY);
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
221
mtr_memo_slot_release(mtr, slot);
311
/***************************************************//**
225
/*******************************************************
312
226
Releases an object in the memo stack. */
315
229
mtr_memo_release(
316
230
/*=============*/
317
mtr_t* mtr, /*!< in: mtr */
318
void* object, /*!< in: object */
319
ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */
231
mtr_t* mtr, /* in: mtr */
232
void* object, /* in: object */
233
ulint type) /* in: object type: MTR_MEMO_S_LOCK, ... */
321
235
mtr_memo_slot_t* slot;
322
236
dyn_array_t* memo;
331
245
offset = dyn_array_get_data_size(memo);
333
log_flush_order_mutex_enter();
334
247
while (offset > 0) {
335
248
offset -= sizeof(mtr_memo_slot_t);
337
slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
339
if (object == slot->object && type == slot->type) {
341
/* We cannot release a page that has been written
342
to in the middle of a mini-transaction. */
344
ut_ad(!(mtr->modifications
345
&& slot->type == MTR_MEMO_PAGE_X_FIX));
250
slot = dyn_array_get_element(memo, offset);
252
if ((object == slot->object) && (type == slot->type)) {
347
254
mtr_memo_slot_release(mtr, slot);
352
log_flush_order_mutex_exit();
354
#endif /* !UNIV_HOTBACKUP */
356
/********************************************************//**
357
Reads 1 - 4 bytes from a file page buffered in the buffer pool.
358
@return value read */
261
/************************************************************
262
Reads 1 - 4 bytes from a file page buffered in the buffer pool. */
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 */
267
/* out: value read */
268
const byte* ptr, /* in: pointer from where to read */
269
ulint type, /* in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
270
mtr_t* mtr __attribute__((unused)))
271
/* in: mini-transaction handle */
368
273
ut_ad(mtr->state == MTR_ACTIVE);
369
274
ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
286
/************************************************************
287
Reads 8 bytes from a file page buffered in the buffer pool. */
292
/* out: value read */
293
const byte* ptr, /* in: pointer from where to read */
294
mtr_t* mtr __attribute__((unused)))
295
/* in: mini-transaction handle */
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
return(mach_read_from_8(ptr));
381
303
#ifdef UNIV_DEBUG
382
# ifndef UNIV_HOTBACKUP
383
/**********************************************************//**
384
Checks if memo contains the given page.
385
@return TRUE if contains */
304
/**************************************************************
305
Checks if memo contains the given page. */
388
308
mtr_memo_contains_page(
389
309
/*===================*/
390
mtr_t* mtr, /*!< in: mtr */
391
const byte* ptr, /*!< in: pointer to buffer frame */
392
ulint type) /*!< in: type of object */
310
/* out: TRUE if contains */
311
mtr_t* mtr, /* in: mtr */
312
const byte* ptr, /* in: pointer to buffer frame */
313
ulint type) /* in: type of object */
394
return(mtr_memo_contains(mtr, buf_block_align(ptr), type));
317
buf_pool_mutex_enter();
318
ret = mtr_memo_contains(mtr, buf_block_align(ptr), type);
319
buf_pool_mutex_exit();
397
/*********************************************************//**
323
/*************************************************************
398
324
Prints info of an mtr handle. */
403
mtr_t* mtr) /*!< in: mtr */
329
mtr_t* mtr) /* in: mtr */
406
332
"Mini-transaction handle: memo size %lu bytes"