~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2008-11-16 05:36:13 UTC
  • mto: (584.1.9 devel)
  • mto: This revision was merged to the branch mainline in revision 589.
  • Revision ID: monty@inaugust.com-20081116053613-bld4rqxhlkb49c02
Split out cache_row and type_holder.

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
 
        void *rseg_buf= mem_zalloc(sizeof(trx_rseg_t));
201
 
        rseg = static_cast<trx_rseg_t *>(rseg_buf);
202
 
 
203
 
        rseg->id = id;
204
 
        rseg->space = space;
205
 
        rseg->zip_size = zip_size;
206
 
        rseg->page_no = page_no;
207
 
 
208
 
        mutex_create(rseg_mutex_key, &rseg->mutex, SYNC_RSEG);
209
 
 
210
 
        UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg);
211
 
 
212
 
        trx_sys_set_nth_rseg(trx_sys, id, rseg);
213
 
 
214
 
        rseg_header = trx_rsegf_get_new(space, zip_size, page_no, mtr);
215
 
 
216
 
        rseg->max_size = mtr_read_ulint(rseg_header + TRX_RSEG_MAX_SIZE,
217
 
                                        MLOG_4BYTES, mtr);
218
 
 
219
 
        /* Initialize the undo log lists according to the rseg header */
220
 
 
221
 
        sum_of_undo_sizes = trx_undo_lists_init(rseg);
222
 
 
223
 
        rseg->curr_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
224
 
                                         MLOG_4BYTES, mtr)
225
 
                + 1 + sum_of_undo_sizes;
226
 
 
227
 
        len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr);
228
 
        if (len > 0) {
229
 
                trx_sys->rseg_history_len += len;
230
 
 
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;
235
 
 
236
 
                undo_log_hdr = trx_undo_page_get(rseg->space, rseg->zip_size,
237
 
                                                 node_addr.page,
238
 
                                                 mtr) + node_addr.boffset;
239
 
 
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);
244
 
        } else {
245
 
                rseg->last_page_no = FIL_NULL;
246
 
        }
247
 
 
248
 
        return(rseg);
249
 
}
250
 
 
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. */
254
 
static
255
 
void
256
 
trx_rseg_create_instance(
257
 
/*=====================*/
258
 
        trx_sysf_t*     sys_header,     /*!< in: trx system header */
259
 
        mtr_t*          mtr)            /*!< in: mtr */
260
 
{
261
 
        ulint           i;
262
 
 
263
 
        for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
264
 
                ulint   page_no;
265
 
 
266
 
                page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
267
 
 
268
 
                if (page_no == FIL_NULL) {
269
 
                        trx_sys_set_nth_rseg(trx_sys, i, NULL);
270
 
                } else {
271
 
                        ulint           space;
272
 
                        ulint           zip_size;
273
 
                        trx_rseg_t*     rseg = NULL;
274
 
 
275
 
                        ut_a(!trx_rseg_get_on_id(i));
276
 
 
277
 
                        space = trx_sysf_rseg_get_space(sys_header, i, mtr);
278
 
 
279
 
                        zip_size = space ? fil_space_get_zip_size(space) : 0;
280
 
 
281
 
                        rseg = trx_rseg_mem_create(
282
 
                                i, space, zip_size, page_no, mtr);
283
 
 
284
 
                        ut_a(rseg->id == i);
285
 
                }
286
 
        }
287
 
}
288
 
 
289
 
/*********************************************************************
290
 
Creates a rollback segment.
291
 
@return pointer to new rollback segment if create successful */
292
 
UNIV_INTERN
293
 
trx_rseg_t*
294
 
trx_rseg_create(void)
295
 
/*=================*/
296
 
{
297
 
        mtr_t           mtr;
298
 
        ulint           slot_no;
299
 
        trx_rseg_t*     rseg = NULL;
300
 
 
301
 
        mtr_start(&mtr);
302
 
 
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);
306
 
 
307
 
        mutex_enter(&kernel_mutex);
308
 
 
309
 
        slot_no = trx_sysf_rseg_find_free(&mtr);
310
 
 
311
 
        if (slot_no != ULINT_UNDEFINED) {
312
 
                ulint           space;
313
 
                ulint           page_no;
314
 
                ulint           zip_size;
315
 
                trx_sysf_t*     sys_header;
316
 
 
317
 
                page_no = trx_rseg_header_create(
318
 
                        TRX_SYS_SPACE, 0, ULINT_MAX, slot_no, &mtr);
319
 
 
320
 
                ut_a(page_no != FIL_NULL);
321
 
 
322
 
                ut_ad(!trx_rseg_get_on_id(slot_no));
323
 
 
324
 
                sys_header = trx_sysf_get(&mtr);
325
 
 
326
 
                space = trx_sysf_rseg_get_space(sys_header, slot_no, &mtr);
327
 
 
328
 
                zip_size = space ? fil_space_get_zip_size(space) : 0;
329
 
 
330
 
                rseg = trx_rseg_mem_create(
331
 
                        slot_no, space, zip_size, page_no, &mtr);
332
 
        }
333
 
 
334
 
        mutex_exit(&kernel_mutex);
335
 
        mtr_commit(&mtr);
336
 
 
337
 
        return(rseg);
338
 
}
339
 
 
340
 
/********************************************************************
341
 
Initialize the rollback instance list. */
342
 
UNIV_INTERN
343
 
void
344
 
trx_rseg_list_and_array_init(
345
 
/*=========================*/
346
 
        trx_sysf_t*     sys_header,     /* in: trx system header */
347
 
        mtr_t*          mtr)            /* in: mtr */
348
 
{
349
 
        UT_LIST_INIT(trx_sys->rseg_list);
350
 
 
351
 
        trx_sys->rseg_history_len = 0;
352
 
 
353
 
        trx_rseg_create_instance(sys_header, mtr);
354
 
}
355