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
/**************************************************//**
21
Mini-transaction buffer
23
Created 11/26/1995 Heikki Tuuri
24
*******************************************************/
33
#include "page0types.h"
37
#ifndef UNIV_HOTBACKUP
38
# include "log0recv.h"
39
/*****************************************************************//**
40
Releases the item in the slot given. */
43
mtr_memo_slot_release(
44
/*==================*/
45
mtr_t* mtr, /*!< in: mtr */
46
mtr_memo_slot_t* slot) /*!< in: memo slot */
53
object = slot->object;
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);
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 */
68
rw_lock_x_unlock((rw_lock_t*)object);
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
86
mtr_t* mtr) /*!< in: mtr */
88
mtr_memo_slot_t* slot;
93
ut_ad(mtr->magic_n == MTR_MAGIC_N);
94
ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
98
offset = dyn_array_get_data_size(memo);
101
offset -= sizeof(mtr_memo_slot_t);
102
slot = dyn_array_get_element(memo, offset);
104
mtr_memo_slot_release(mtr, slot);
108
/************************************************************//**
109
Writes the contents of a mini-transaction log, if any, to the database log. */
112
mtr_log_reserve_and_write(
113
/*======================*/
114
mtr_t* mtr) /*!< in: mtr */
125
first_data = dyn_block_get_data(mlog);
127
if (mtr->n_log_recs > 1) {
128
mlog_catenate_ulint(mtr, MLOG_MULTI_REC_END, MLOG_1BYTE);
130
*first_data = (byte)((ulint)*first_data
131
| MLOG_SINGLE_REC_FLAG);
134
if (mlog->heap == NULL) {
135
mtr->end_lsn = log_reserve_and_write_fast(
136
first_data, dyn_block_get_used(mlog),
144
data_size = dyn_array_get_data_size(mlog);
146
/* Open the database log for log_write_low */
147
mtr->start_lsn = log_reserve_and_open(data_size);
149
if (mtr->log_mode == MTR_LOG_ALL) {
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);
159
ut_ad(mtr->log_mode == MTR_LOG_NONE);
163
mtr->end_lsn = log_close();
165
#endif /* !UNIV_HOTBACKUP */
167
/***************************************************************//**
168
Commits a mini-transaction. */
173
mtr_t* mtr) /*!< in: mini-transaction */
175
#ifndef UNIV_HOTBACKUP
177
#endif /* !UNIV_HOTBACKUP */
180
ut_ad(mtr->magic_n == MTR_MAGIC_N);
181
ut_ad(mtr->state == MTR_ACTIVE);
182
ut_d(mtr->state = MTR_COMMITTING);
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;
190
mtr_log_reserve_and_write(mtr);
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. */
201
mtr_memo_pop_all(mtr);
206
#endif /* !UNIV_HOTBACKUP */
208
ut_d(mtr->state = MTR_COMMITTED);
209
dyn_array_free(&(mtr->memo));
210
dyn_array_free(&(mtr->log));
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. */
220
mtr_rollback_to_savepoint(
221
/*======================*/
222
mtr_t* mtr, /*!< in: mtr */
223
ulint savepoint) /*!< in: savepoint */
225
mtr_memo_slot_t* slot;
230
ut_ad(mtr->magic_n == MTR_MAGIC_N);
231
ut_ad(mtr->state == MTR_ACTIVE);
235
offset = dyn_array_get_data_size(memo);
236
ut_ad(offset >= savepoint);
238
while (offset > savepoint) {
239
offset -= sizeof(mtr_memo_slot_t);
241
slot = dyn_array_get_element(memo, offset);
243
ut_ad(slot->type != MTR_MEMO_MODIFY);
244
mtr_memo_slot_release(mtr, slot);
248
/***************************************************//**
249
Releases an object in the memo stack. */
254
mtr_t* mtr, /*!< in: mtr */
255
void* object, /*!< in: object */
256
ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */
258
mtr_memo_slot_t* slot;
263
ut_ad(mtr->magic_n == MTR_MAGIC_N);
264
ut_ad(mtr->state == MTR_ACTIVE);
268
offset = dyn_array_get_data_size(memo);
271
offset -= sizeof(mtr_memo_slot_t);
273
slot = dyn_array_get_element(memo, offset);
275
if ((object == slot->object) && (type == slot->type)) {
277
mtr_memo_slot_release(mtr, slot);
283
#endif /* !UNIV_HOTBACKUP */
285
/********************************************************//**
286
Reads 1 - 4 bytes from a file page buffered in the buffer pool.
287
@return value read */
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 */
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));
305
ut_ad(type == MLOG_4BYTES);
306
return(mach_read_from_4(ptr));
310
/********************************************************//**
311
Reads 8 bytes from a file page buffered in the buffer pool.
312
@return value read */
317
const byte* ptr, /*!< in: pointer from where to read */
318
mtr_t* mtr __attribute__((unused)))
319
/*!< in: mini-transaction handle */
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));
328
# ifndef UNIV_HOTBACKUP
329
/**********************************************************//**
330
Checks if memo contains the given page.
331
@return TRUE if contains */
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 */
340
return(mtr_memo_contains(mtr, buf_block_align(ptr), type));
343
/*********************************************************//**
344
Prints info of an mtr handle. */
349
mtr_t* mtr) /*!< in: mtr */
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)));
357
# endif /* !UNIV_HOTBACKUP */
358
#endif /* UNIV_DEBUG */