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., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/******************************************************
20
Mini-transaction buffer
22
Created 11/26/1995 Heikki Tuuri
23
*******************************************************/
32
#include "page0types.h"
36
/*********************************************************************
37
Releases the item in the slot given. */
40
mtr_memo_slot_release(
41
/*==================*/
42
mtr_t* mtr, /* in: mtr */
43
mtr_memo_slot_t* slot) /* in: memo slot */
50
object = slot->object;
53
if (UNIV_LIKELY(object != NULL)) {
54
if (type <= MTR_MEMO_BUF_FIX) {
55
buf_page_release((buf_block_t*)object, type, mtr);
56
} else if (type == MTR_MEMO_S_LOCK) {
57
rw_lock_s_unlock((rw_lock_t*)object);
59
} else if (type != MTR_MEMO_X_LOCK) {
60
ut_ad(type == MTR_MEMO_MODIFY);
61
ut_ad(mtr_memo_contains(mtr, object,
62
MTR_MEMO_PAGE_X_FIX));
63
#endif /* UNIV_DEBUG */
65
rw_lock_x_unlock((rw_lock_t*)object);
72
/**************************************************************
73
Releases the mlocks and other objects stored in an mtr memo. They are released
74
in the order opposite to which they were pushed to the memo. NOTE! It is
75
essential that the x-rw-lock on a modified buffer page is not released before
76
buf_page_note_modification is called for that page! Otherwise, some thread
77
might race to modify it, and the flush list sort order on lsn would be
83
mtr_t* mtr) /* in: mtr */
85
mtr_memo_slot_t* slot;
90
ut_ad(mtr->magic_n == MTR_MAGIC_N);
91
ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
95
offset = dyn_array_get_data_size(memo);
98
offset -= sizeof(mtr_memo_slot_t);
99
slot = dyn_array_get_element(memo, offset);
101
mtr_memo_slot_release(mtr, slot);
105
/****************************************************************
106
Writes the contents of a mini-transaction log, if any, to the database log. */
109
mtr_log_reserve_and_write(
110
/*======================*/
111
mtr_t* mtr) /* in: mtr */
123
first_data = dyn_block_get_data(mlog);
125
if (mtr->n_log_recs > 1) {
126
mlog_catenate_ulint(mtr, MLOG_MULTI_REC_END, MLOG_1BYTE);
128
*first_data = (byte)((ulint)*first_data
129
| MLOG_SINGLE_REC_FLAG);
132
if (mlog->heap == NULL) {
133
mtr->end_lsn = log_reserve_and_write_fast(
134
first_data, dyn_block_get_used(mlog),
135
&(mtr->start_lsn), &success);
142
data_size = dyn_array_get_data_size(mlog);
144
/* Open the database log for log_write_low */
145
mtr->start_lsn = log_reserve_and_open(data_size);
147
if (mtr->log_mode == MTR_LOG_ALL) {
151
while (block != NULL) {
152
log_write_low(dyn_block_get_data(block),
153
dyn_block_get_used(block));
154
block = dyn_array_get_next_block(mlog, block);
157
ut_ad(mtr->log_mode == MTR_LOG_NONE);
161
mtr->end_lsn = log_close();
164
/*******************************************************************
165
Commits a mini-transaction. */
170
mtr_t* mtr) /* in: mini-transaction */
175
ut_ad(mtr->magic_n == MTR_MAGIC_N);
176
ut_ad(mtr->state == MTR_ACTIVE);
177
ut_d(mtr->state = MTR_COMMITTING);
179
write_log = mtr->modifications && mtr->n_log_recs;
182
mtr_log_reserve_and_write(mtr);
185
/* We first update the modification info to buffer pages, and only
186
after that release the log mutex: this guarantees that when the log
187
mutex is free, all buffer pages contain an up-to-date info of their
188
modifications. This fact is used in making a checkpoint when we look
189
at the oldest modification of any page in the buffer pool. It is also
190
required when we insert modified buffer pages in to the flush list
191
which must be sorted on oldest_modification. */
193
mtr_memo_pop_all(mtr);
199
ut_d(mtr->state = MTR_COMMITTED);
200
dyn_array_free(&(mtr->memo));
201
dyn_array_free(&(mtr->log));
204
/**************************************************************
205
Releases the latches stored in an mtr memo down to a savepoint.
206
NOTE! The mtr must not have made changes to buffer pages after the
207
savepoint, as these can be handled only by mtr_commit. */
210
mtr_rollback_to_savepoint(
211
/*======================*/
212
mtr_t* mtr, /* in: mtr */
213
ulint savepoint) /* in: savepoint */
215
mtr_memo_slot_t* slot;
220
ut_ad(mtr->magic_n == MTR_MAGIC_N);
221
ut_ad(mtr->state == MTR_ACTIVE);
225
offset = dyn_array_get_data_size(memo);
226
ut_ad(offset >= savepoint);
228
while (offset > savepoint) {
229
offset -= sizeof(mtr_memo_slot_t);
231
slot = dyn_array_get_element(memo, offset);
233
ut_ad(slot->type != MTR_MEMO_MODIFY);
234
mtr_memo_slot_release(mtr, slot);
238
/*******************************************************
239
Releases an object in the memo stack. */
244
mtr_t* mtr, /* in: mtr */
245
void* object, /* in: object */
246
ulint type) /* in: object type: MTR_MEMO_S_LOCK, ... */
248
mtr_memo_slot_t* slot;
253
ut_ad(mtr->magic_n == MTR_MAGIC_N);
254
ut_ad(mtr->state == MTR_ACTIVE);
258
offset = dyn_array_get_data_size(memo);
261
offset -= sizeof(mtr_memo_slot_t);
263
slot = dyn_array_get_element(memo, offset);
265
if ((object == slot->object) && (type == slot->type)) {
267
mtr_memo_slot_release(mtr, slot);
274
/************************************************************
275
Reads 1 - 4 bytes from a file page buffered in the buffer pool. */
280
/* out: value read */
281
const byte* ptr, /* in: pointer from where to read */
282
ulint type, /* in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
283
mtr_t* mtr __attribute__((unused)))
284
/* in: mini-transaction handle */
286
ut_ad(mtr->state == MTR_ACTIVE);
287
ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
288
|| mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX));
289
if (type == MLOG_1BYTE) {
290
return(mach_read_from_1(ptr));
291
} else if (type == MLOG_2BYTES) {
292
return(mach_read_from_2(ptr));
294
ut_ad(type == MLOG_4BYTES);
295
return(mach_read_from_4(ptr));
299
/************************************************************
300
Reads 8 bytes from a file page buffered in the buffer pool. */
305
/* out: value read */
306
const byte* ptr, /* in: pointer from where to read */
307
mtr_t* mtr __attribute__((unused)))
308
/* in: mini-transaction handle */
310
ut_ad(mtr->state == MTR_ACTIVE);
311
ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
312
|| mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX));
313
return(mach_read_from_8(ptr));
317
/**************************************************************
318
Checks if memo contains the given page. */
321
mtr_memo_contains_page(
322
/*===================*/
323
/* out: TRUE if contains */
324
mtr_t* mtr, /* in: mtr */
325
const byte* ptr, /* in: pointer to buffer frame */
326
ulint type) /* in: type of object */
328
return(mtr_memo_contains(mtr, buf_block_align(ptr), type));
331
/*************************************************************
332
Prints info of an mtr handle. */
337
mtr_t* mtr) /* in: mtr */
340
"Mini-transaction handle: memo size %lu bytes"
341
" log size %lu bytes\n",
342
(ulong) dyn_array_get_data_size(&(mtr->memo)),
343
(ulong) dyn_array_get_data_size(&(mtr->log)));
345
#endif /* UNIV_DEBUG */