1
/*****************************************************************************
3
Copyright (C) 1996, 2010, 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
/**************************************************//**
23
Created 3/26/1996 Heikki Tuuri
24
*******************************************************/
29
#include "trx0rseg.ic"
35
#include "trx0purge.h"
38
/* Key to register rseg_mutex_key with performance schema */
39
UNIV_INTERN mysql_pfs_key_t rseg_mutex_key;
40
#endif /* UNIV_PFS_MUTEX */
42
/******************************************************************//**
43
Looks for a rollback segment, based on the rollback segment id.
44
@return rollback segment */
49
ulint id) /*!< in: rollback segment id */
53
rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
55
while (rseg && rseg->id != id) {
56
rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
62
/****************************************************************//**
63
Creates a rollback segment header. This function is called only when
64
a new rollback segment is created in the database.
65
@return page number of the created segment, FIL_NULL if fail */
68
trx_rseg_header_create(
69
/*===================*/
70
ulint space, /*!< in: space id */
71
ulint zip_size, /*!< in: compressed page size in bytes
72
or 0 for uncompressed pages */
73
ulint max_size, /*!< in: max size in pages */
74
ulint rseg_slot_no, /*!< in: rseg id == slot number in trx sys */
75
mtr_t* mtr) /*!< in: mtr */
79
trx_sysf_t* sys_header;
84
ut_ad(mutex_own(&kernel_mutex));
85
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
88
/* Allocate a new file segment for the rollback segment */
89
block = fseg_create(space, 0,
90
TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr);
98
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
100
page_no = buf_block_get_page_no(block);
102
/* Get the rollback segment file page */
103
rsegf = trx_rsegf_get_new(space, zip_size, page_no, mtr);
105
/* Initialize max size field */
106
mlog_write_ulint(rsegf + TRX_RSEG_MAX_SIZE, max_size,
109
/* Initialize the history list */
111
mlog_write_ulint(rsegf + TRX_RSEG_HISTORY_SIZE, 0, MLOG_4BYTES, mtr);
112
flst_init(rsegf + TRX_RSEG_HISTORY, mtr);
114
/* Reset the undo log slots */
115
for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
117
trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
120
/* Add the rollback segment info to the free slot in
121
the trx system header */
123
sys_header = trx_sysf_get(mtr);
125
trx_sysf_rseg_set_space(sys_header, rseg_slot_no, space, mtr);
126
trx_sysf_rseg_set_page_no(sys_header, rseg_slot_no, page_no, mtr);
131
/***********************************************************************//**
132
Free's an instance of the rollback segment in memory. */
137
trx_rseg_t* rseg) /* in, own: instance to free */
141
mutex_free(&rseg->mutex);
143
/* There can't be any active transactions. */
144
ut_a(UT_LIST_GET_LEN(rseg->update_undo_list) == 0);
145
ut_a(UT_LIST_GET_LEN(rseg->insert_undo_list) == 0);
147
undo = UT_LIST_GET_FIRST(rseg->update_undo_cached);
149
while (undo != NULL) {
150
trx_undo_t* prev_undo = undo;
152
undo = UT_LIST_GET_NEXT(undo_list, undo);
153
UT_LIST_REMOVE(undo_list, rseg->update_undo_cached, prev_undo);
155
trx_undo_mem_free(prev_undo);
158
undo = UT_LIST_GET_FIRST(rseg->insert_undo_cached);
160
while (undo != NULL) {
161
trx_undo_t* prev_undo = undo;
163
undo = UT_LIST_GET_NEXT(undo_list, undo);
164
UT_LIST_REMOVE(undo_list, rseg->insert_undo_cached, prev_undo);
166
trx_undo_mem_free(prev_undo);
169
trx_sys_set_nth_rseg(trx_sys, rseg->id, NULL);
174
/***************************************************************************
175
Creates and initializes a rollback segment object. The values for the
176
fields are read from the header. The object is inserted to the rseg
177
list of the trx system object and a pointer is inserted in the rseg
178
array in the trx system object.
179
@return own: rollback segment object */
184
ulint id, /*!< in: rollback segment id */
185
ulint space, /*!< in: space where the segment placed */
186
ulint zip_size, /*!< in: compressed page size in bytes
187
or 0 for uncompressed pages */
188
ulint page_no, /*!< in: page number of the segment header */
189
mtr_t* mtr) /*!< in: mtr */
193
fil_addr_t node_addr;
194
trx_rsegf_t* rseg_header;
195
trx_ulogf_t* undo_log_hdr;
196
ulint sum_of_undo_sizes;
198
ut_ad(mutex_own(&kernel_mutex));
200
void *rseg_buf= mem_zalloc(sizeof(trx_rseg_t));
201
rseg = static_cast<trx_rseg_t *>(rseg_buf);
205
rseg->zip_size = zip_size;
206
rseg->page_no = page_no;
208
mutex_create(rseg_mutex_key, &rseg->mutex, SYNC_RSEG);
210
UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg);
212
trx_sys_set_nth_rseg(trx_sys, id, rseg);
214
rseg_header = trx_rsegf_get_new(space, zip_size, page_no, mtr);
216
rseg->max_size = mtr_read_ulint(rseg_header + TRX_RSEG_MAX_SIZE,
219
/* Initialize the undo log lists according to the rseg header */
221
sum_of_undo_sizes = trx_undo_lists_init(rseg);
223
rseg->curr_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
225
+ 1 + sum_of_undo_sizes;
227
len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr);
229
trx_sys->rseg_history_len += len;
231
node_addr = trx_purge_get_log_from_hist(
232
flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
233
rseg->last_page_no = node_addr.page;
234
rseg->last_offset = node_addr.boffset;
236
undo_log_hdr = trx_undo_page_get(rseg->space, rseg->zip_size,
238
mtr) + node_addr.boffset;
240
rseg->last_trx_no = mach_read_from_8(
241
undo_log_hdr + TRX_UNDO_TRX_NO);
242
rseg->last_del_marks = mtr_read_ulint(
243
undo_log_hdr + TRX_UNDO_DEL_MARKS, MLOG_2BYTES, mtr);
245
rseg->last_page_no = FIL_NULL;
251
/********************************************************************
252
Creates the memory copies for the rollback segments and initializes the
253
rseg list and array in trx_sys at a database startup. */
256
trx_rseg_create_instance(
257
/*=====================*/
258
trx_sysf_t* sys_header, /*!< in: trx system header */
259
mtr_t* mtr) /*!< in: mtr */
263
for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
266
page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
268
if (page_no == FIL_NULL) {
269
trx_sys_set_nth_rseg(trx_sys, i, NULL);
273
trx_rseg_t* rseg = NULL;
275
ut_a(!trx_rseg_get_on_id(i));
277
space = trx_sysf_rseg_get_space(sys_header, i, mtr);
279
zip_size = space ? fil_space_get_zip_size(space) : 0;
281
rseg = trx_rseg_mem_create(
282
i, space, zip_size, page_no, mtr);
289
/*********************************************************************
290
Creates a rollback segment.
291
@return pointer to new rollback segment if create successful */
294
trx_rseg_create(void)
295
/*=================*/
299
trx_rseg_t* rseg = NULL;
303
/* To obey the latching order, acquire the file space
304
x-latch before the kernel mutex. */
305
mtr_x_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), &mtr);
307
mutex_enter(&kernel_mutex);
309
slot_no = trx_sysf_rseg_find_free(&mtr);
311
if (slot_no != ULINT_UNDEFINED) {
315
trx_sysf_t* sys_header;
317
page_no = trx_rseg_header_create(
318
TRX_SYS_SPACE, 0, ULINT_MAX, slot_no, &mtr);
320
ut_a(page_no != FIL_NULL);
322
ut_ad(!trx_rseg_get_on_id(slot_no));
324
sys_header = trx_sysf_get(&mtr);
326
space = trx_sysf_rseg_get_space(sys_header, slot_no, &mtr);
328
zip_size = space ? fil_space_get_zip_size(space) : 0;
330
rseg = trx_rseg_mem_create(
331
slot_no, space, zip_size, page_no, &mtr);
334
mutex_exit(&kernel_mutex);
340
/********************************************************************
341
Initialize the rollback instance list. */
344
trx_rseg_list_and_array_init(
345
/*=========================*/
346
trx_sysf_t* sys_header, /* in: trx system header */
347
mtr_t* mtr) /* in: mtr */
349
UT_LIST_INIT(trx_sys->rseg_list);
351
trx_sys->rseg_history_len = 0;
353
trx_rseg_create_instance(sys_header, mtr);