~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/trx/trx0rseg.c

Lowercase plugin name prefix.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (c) 1996, 2010, 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 trx/trx0rseg.c
21
 
Rollback segment
22
 
 
23
 
Created 3/26/1996 Heikki Tuuri
24
 
*******************************************************/
25
 
 
26
 
#include "trx0rseg.h"
27
 
 
28
 
#ifdef UNIV_NONINL
29
 
#include "trx0rseg.ic"
30
 
#endif
31
 
 
32
 
#include "trx0undo.h"
33
 
#include "fut0lst.h"
34
 
#include "srv0srv.h"
35
 
#include "trx0purge.h"
36
 
 
37
 
#ifdef UNIV_PFS_MUTEX
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 */
41
 
 
42
 
/******************************************************************//**
43
 
Looks for a rollback segment, based on the rollback segment id.
44
 
@return rollback segment */
45
 
UNIV_INTERN
46
 
trx_rseg_t*
47
 
trx_rseg_get_on_id(
48
 
/*===============*/
49
 
        ulint   id)     /*!< in: rollback segment id */
50
 
{
51
 
        trx_rseg_t*     rseg;
52
 
 
53
 
        rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
54
 
 
55
 
        while (rseg && rseg->id != id) {
56
 
                rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
57
 
        }
58
 
 
59
 
        return(rseg);
60
 
}
61
 
 
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 */
66
 
UNIV_INTERN
67
 
ulint
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 */
76
 
{
77
 
        ulint           page_no;
78
 
        trx_rsegf_t*    rsegf;
79
 
        trx_sysf_t*     sys_header;
80
 
        ulint           i;
81
 
        buf_block_t*    block;
82
 
 
83
 
        ut_ad(mtr);
84
 
        ut_ad(mutex_own(&kernel_mutex));
85
 
        ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
86
 
                                MTR_MEMO_X_LOCK));
87
 
 
88
 
        /* Allocate a new file segment for the rollback segment */
89
 
        block = fseg_create(space, 0,
90
 
                            TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr);
91
 
 
92
 
        if (block == NULL) {
93
 
                /* No space left */
94
 
 
95
 
                return(FIL_NULL);
96
 
        }
97
 
 
98
 
        buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
99
 
 
100
 
        page_no = buf_block_get_page_no(block);
101
 
 
102
 
        /* Get the rollback segment file page */
103
 
        rsegf = trx_rsegf_get_new(space, zip_size, page_no, mtr);
104
 
 
105
 
        /* Initialize max size field */
106
 
        mlog_write_ulint(rsegf + TRX_RSEG_MAX_SIZE, max_size,
107
 
                         MLOG_4BYTES, mtr);
108
 
 
109
 
        /* Initialize the history list */
110
 
 
111
 
        mlog_write_ulint(rsegf + TRX_RSEG_HISTORY_SIZE, 0, MLOG_4BYTES, mtr);
112
 
        flst_init(rsegf + TRX_RSEG_HISTORY, mtr);
113
 
 
114
 
        /* Reset the undo log slots */
115
 
        for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
116
 
 
117
 
                trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
118
 
        }
119
 
 
120
 
        /* Add the rollback segment info to the free slot in
121
 
        the trx system header */
122
 
 
123
 
        sys_header = trx_sysf_get(mtr);
124
 
 
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);
127
 
 
128
 
        return(page_no);
129
 
}
130
 
 
131
 
/***********************************************************************//**
132
 
Free's an instance of the rollback segment in memory. */
133
 
UNIV_INTERN
134
 
void
135
 
trx_rseg_mem_free(
136
 
/*==============*/
137
 
        trx_rseg_t*     rseg)   /* in, own: instance to free */
138
 
{
139
 
        trx_undo_t*     undo;
140
 
 
141
 
        mutex_free(&rseg->mutex);
142
 
 
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);
146
 
 
147
 
        undo = UT_LIST_GET_FIRST(rseg->update_undo_cached);
148
 
 
149
 
        while (undo != NULL) {
150
 
                trx_undo_t*     prev_undo = undo;
151
 
 
152
 
                undo = UT_LIST_GET_NEXT(undo_list, undo);
153
 
                UT_LIST_REMOVE(undo_list, rseg->update_undo_cached, prev_undo);
154
 
 
155
 
                trx_undo_mem_free(prev_undo);
156
 
        }
157
 
 
158
 
        undo = UT_LIST_GET_FIRST(rseg->insert_undo_cached);
159
 
 
160
 
        while (undo != NULL) {
161
 
                trx_undo_t*     prev_undo = undo;
162
 
 
163
 
                undo = UT_LIST_GET_NEXT(undo_list, undo);
164
 
                UT_LIST_REMOVE(undo_list, rseg->insert_undo_cached, prev_undo);
165
 
 
166
 
                trx_undo_mem_free(prev_undo);
167
 
        }
168
 
 
169
 
        trx_sys_set_nth_rseg(trx_sys, rseg->id, NULL);
170
 
 
171
 
        mem_free(rseg);
172
 
}
173
 
 
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 */
180
 
static
181
 
trx_rseg_t*
182
 
trx_rseg_mem_create(
183
 
/*================*/
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 */
190
 
{
191
 
        ulint           len;
192
 
        trx_rseg_t*     rseg;
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;
197
 
 
198
 
        ut_ad(mutex_own(&kernel_mutex));
199
 
 
200
 
        rseg = mem_zalloc(sizeof(trx_rseg_t));
201
 
 
202
 
        rseg->id = id;
203
 
        rseg->space = space;
204
 
        rseg->zip_size = zip_size;
205
 
        rseg->page_no = page_no;
206
 
 
207
 
        mutex_create(rseg_mutex_key, &rseg->mutex, SYNC_RSEG);
208
 
 
209
 
        UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg);
210
 
 
211
 
        trx_sys_set_nth_rseg(trx_sys, id, rseg);
212
 
 
213
 
        rseg_header = trx_rsegf_get_new(space, zip_size, page_no, mtr);
214
 
 
215
 
        rseg->max_size = mtr_read_ulint(rseg_header + TRX_RSEG_MAX_SIZE,
216
 
                                        MLOG_4BYTES, mtr);
217
 
 
218
 
        /* Initialize the undo log lists according to the rseg header */
219
 
 
220
 
        sum_of_undo_sizes = trx_undo_lists_init(rseg);
221
 
 
222
 
        rseg->curr_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
223
 
                                         MLOG_4BYTES, mtr)
224
 
                + 1 + sum_of_undo_sizes;
225
 
 
226
 
        len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr);
227
 
        if (len > 0) {
228
 
                trx_sys->rseg_history_len += len;
229
 
 
230
 
                node_addr = trx_purge_get_log_from_hist(
231
 
                        flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
232
 
                rseg->last_page_no = node_addr.page;
233
 
                rseg->last_offset = node_addr.boffset;
234
 
 
235
 
                undo_log_hdr = trx_undo_page_get(rseg->space, rseg->zip_size,
236
 
                                                 node_addr.page,
237
 
                                                 mtr) + node_addr.boffset;
238
 
 
239
 
                rseg->last_trx_no = mach_read_from_8(
240
 
                        undo_log_hdr + TRX_UNDO_TRX_NO);
241
 
                rseg->last_del_marks = mtr_read_ulint(
242
 
                        undo_log_hdr + TRX_UNDO_DEL_MARKS, MLOG_2BYTES, mtr);
243
 
        } else {
244
 
                rseg->last_page_no = FIL_NULL;
245
 
        }
246
 
 
247
 
        return(rseg);
248
 
}
249
 
 
250
 
/********************************************************************
251
 
Creates the memory copies for the rollback segments and initializes the
252
 
rseg list and array in trx_sys at a database startup. */
253
 
static
254
 
void
255
 
trx_rseg_create_instance(
256
 
/*=====================*/
257
 
        trx_sysf_t*     sys_header,     /*!< in: trx system header */
258
 
        mtr_t*          mtr)            /*!< in: mtr */
259
 
{
260
 
        ulint           i;
261
 
 
262
 
        for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
263
 
                ulint   page_no;
264
 
 
265
 
                page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
266
 
 
267
 
                if (page_no == FIL_NULL) {
268
 
                        trx_sys_set_nth_rseg(trx_sys, i, NULL);
269
 
                } else {
270
 
                        ulint           space;
271
 
                        ulint           zip_size;
272
 
                        trx_rseg_t*     rseg = NULL;
273
 
 
274
 
                        ut_a(!trx_rseg_get_on_id(i));
275
 
 
276
 
                        space = trx_sysf_rseg_get_space(sys_header, i, mtr);
277
 
 
278
 
                        zip_size = space ? fil_space_get_zip_size(space) : 0;
279
 
 
280
 
                        rseg = trx_rseg_mem_create(
281
 
                                i, space, zip_size, page_no, mtr);
282
 
 
283
 
                        ut_a(rseg->id == i);
284
 
                }
285
 
        }
286
 
}
287
 
 
288
 
/*********************************************************************
289
 
Creates a rollback segment.
290
 
@return pointer to new rollback segment if create successful */
291
 
UNIV_INTERN
292
 
trx_rseg_t*
293
 
trx_rseg_create(void)
294
 
/*=================*/
295
 
{
296
 
        mtr_t           mtr;
297
 
        ulint           slot_no;
298
 
        trx_rseg_t*     rseg = NULL;
299
 
 
300
 
        mtr_start(&mtr);
301
 
 
302
 
        /* To obey the latching order, acquire the file space
303
 
        x-latch before the kernel mutex. */
304
 
        mtr_x_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), &mtr);
305
 
 
306
 
        mutex_enter(&kernel_mutex);
307
 
 
308
 
        slot_no = trx_sysf_rseg_find_free(&mtr);
309
 
 
310
 
        if (slot_no != ULINT_UNDEFINED) {
311
 
                ulint           space;
312
 
                ulint           page_no;
313
 
                ulint           zip_size;
314
 
                trx_sysf_t*     sys_header;
315
 
 
316
 
                page_no = trx_rseg_header_create(
317
 
                        TRX_SYS_SPACE, 0, ULINT_MAX, slot_no, &mtr);
318
 
 
319
 
                ut_a(page_no != FIL_NULL);
320
 
 
321
 
                ut_ad(!trx_rseg_get_on_id(slot_no));
322
 
 
323
 
                sys_header = trx_sysf_get(&mtr);
324
 
 
325
 
                space = trx_sysf_rseg_get_space(sys_header, slot_no, &mtr);
326
 
 
327
 
                zip_size = space ? fil_space_get_zip_size(space) : 0;
328
 
 
329
 
                rseg = trx_rseg_mem_create(
330
 
                        slot_no, space, zip_size, page_no, &mtr);
331
 
        }
332
 
 
333
 
        mutex_exit(&kernel_mutex);
334
 
        mtr_commit(&mtr);
335
 
 
336
 
        return(rseg);
337
 
}
338
 
 
339
 
/********************************************************************
340
 
Initialize the rollback instance list. */
341
 
UNIV_INTERN
342
 
void
343
 
trx_rseg_list_and_array_init(
344
 
/*=========================*/
345
 
        trx_sysf_t*     sys_header,     /* in: trx system header */
346
 
        mtr_t*          mtr)            /* in: mtr */
347
 
{
348
 
        UT_LIST_INIT(trx_sys->rseg_list);
349
 
 
350
 
        trx_sys->rseg_history_len = 0;
351
 
 
352
 
        trx_rseg_create_instance(sys_header, mtr);
353
 
}
354