~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/include/trx0sys.ic

Merge Joe, plus I updated the tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (C) 1996, 2009, 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 include/trx0sys.ic
21
 
Transaction system
22
 
 
23
 
Created 3/26/1996 Heikki Tuuri
24
 
*******************************************************/
25
 
 
26
 
#include "trx0trx.h"
27
 
#include "data0type.h"
28
 
#ifndef UNIV_HOTBACKUP
29
 
# include "srv0srv.h"
30
 
# include "mtr0log.h"
31
 
 
32
 
/* The typedef for rseg slot in the file copy */
33
 
typedef byte    trx_sysf_rseg_t;
34
 
 
35
 
/* Rollback segment specification slot offsets */
36
 
/*-------------------------------------------------------------*/
37
 
#define TRX_SYS_RSEG_SPACE      0       /* space where the the segment
38
 
                                        header is placed; starting with
39
 
                                        MySQL/InnoDB 5.1.7, this is
40
 
                                        UNIV_UNDEFINED if the slot is unused */
41
 
#define TRX_SYS_RSEG_PAGE_NO    4       /*  page number where the the segment
42
 
                                        header is placed; this is FIL_NULL
43
 
                                        if the slot is unused */
44
 
/*-------------------------------------------------------------*/
45
 
/* Size of a rollback segment specification slot */
46
 
#define TRX_SYS_RSEG_SLOT_SIZE  8
47
 
 
48
 
/*****************************************************************//**
49
 
Writes the value of max_trx_id to the file based trx system header. */
50
 
UNIV_INTERN
51
 
void
52
 
trx_sys_flush_max_trx_id(void);
53
 
/*==========================*/
54
 
 
55
 
/***************************************************************//**
56
 
Checks if a page address is the trx sys header page.
57
 
@return TRUE if trx sys header page */
58
 
UNIV_INLINE
59
 
ibool
60
 
trx_sys_hdr_page(
61
 
/*=============*/
62
 
        ulint   space,  /*!< in: space */
63
 
        ulint   page_no)/*!< in: page number */
64
 
{
65
 
        if ((space == TRX_SYS_SPACE) && (page_no == TRX_SYS_PAGE_NO)) {
66
 
 
67
 
                return(TRUE);
68
 
        }
69
 
 
70
 
        return(FALSE);
71
 
}
72
 
 
73
 
/***************************************************************//**
74
 
Gets the pointer in the nth slot of the rseg array.
75
 
@return pointer to rseg object, NULL if slot not in use */
76
 
UNIV_INLINE
77
 
trx_rseg_t*
78
 
trx_sys_get_nth_rseg(
79
 
/*=================*/
80
 
        trx_sys_t*      sys,    /*!< in: trx system */
81
 
        ulint           n)      /*!< in: index of slot */
82
 
{
83
 
        ut_ad(mutex_own(&(kernel_mutex)));
84
 
        ut_ad(n < TRX_SYS_N_RSEGS);
85
 
 
86
 
        return(sys->rseg_array[n]);
87
 
}
88
 
 
89
 
/***************************************************************//**
90
 
Sets the pointer in the nth slot of the rseg array. */
91
 
UNIV_INLINE
92
 
void
93
 
trx_sys_set_nth_rseg(
94
 
/*=================*/
95
 
        trx_sys_t*      sys,    /*!< in: trx system */
96
 
        ulint           n,      /*!< in: index of slot */
97
 
        trx_rseg_t*     rseg)   /*!< in: pointer to rseg object, NULL if slot
98
 
                                not in use */
99
 
{
100
 
        ut_ad(n < TRX_SYS_N_RSEGS);
101
 
 
102
 
        sys->rseg_array[n] = rseg;
103
 
}
104
 
 
105
 
/**********************************************************************//**
106
 
Gets a pointer to the transaction system header and x-latches its page.
107
 
@return pointer to system header, page x-latched. */
108
 
UNIV_INLINE
109
 
trx_sysf_t*
110
 
trx_sysf_get(
111
 
/*=========*/
112
 
        mtr_t*  mtr)    /*!< in: mtr */
113
 
{
114
 
        buf_block_t*    block;
115
 
        trx_sysf_t*     header;
116
 
 
117
 
        ut_ad(mtr);
118
 
 
119
 
        block = buf_page_get(TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO,
120
 
                             RW_X_LATCH, mtr);
121
 
        buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
122
 
 
123
 
        header = TRX_SYS + buf_block_get_frame(block);
124
 
 
125
 
        return(header);
126
 
}
127
 
 
128
 
/*****************************************************************//**
129
 
Gets the space of the nth rollback segment slot in the trx system
130
 
file copy.
131
 
@return space id */
132
 
UNIV_INLINE
133
 
ulint
134
 
trx_sysf_rseg_get_space(
135
 
/*====================*/
136
 
        trx_sysf_t*     sys_header,     /*!< in: trx sys header */
137
 
        ulint           i,              /*!< in: slot index == rseg id */
138
 
        mtr_t*          mtr)            /*!< in: mtr */
139
 
{
140
 
        ut_ad(mutex_own(&(kernel_mutex)));
141
 
        ut_ad(sys_header);
142
 
        ut_ad(i < TRX_SYS_N_RSEGS);
143
 
 
144
 
        return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS
145
 
                              + i * TRX_SYS_RSEG_SLOT_SIZE
146
 
                              + TRX_SYS_RSEG_SPACE, MLOG_4BYTES, mtr));
147
 
}
148
 
 
149
 
/*****************************************************************//**
150
 
Gets the page number of the nth rollback segment slot in the trx system
151
 
header.
152
 
@return page number, FIL_NULL if slot unused */
153
 
UNIV_INLINE
154
 
ulint
155
 
trx_sysf_rseg_get_page_no(
156
 
/*======================*/
157
 
        trx_sysf_t*     sys_header,     /*!< in: trx system header */
158
 
        ulint           i,              /*!< in: slot index == rseg id */
159
 
        mtr_t*          mtr)            /*!< in: mtr */
160
 
{
161
 
        ut_ad(sys_header);
162
 
        ut_ad(mutex_own(&(kernel_mutex)));
163
 
        ut_ad(i < TRX_SYS_N_RSEGS);
164
 
 
165
 
        return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS
166
 
                              + i * TRX_SYS_RSEG_SLOT_SIZE
167
 
                              + TRX_SYS_RSEG_PAGE_NO, MLOG_4BYTES, mtr));
168
 
}
169
 
 
170
 
/*****************************************************************//**
171
 
Sets the space id of the nth rollback segment slot in the trx system
172
 
file copy. */
173
 
UNIV_INLINE
174
 
void
175
 
trx_sysf_rseg_set_space(
176
 
/*====================*/
177
 
        trx_sysf_t*     sys_header,     /*!< in: trx sys file copy */
178
 
        ulint           i,              /*!< in: slot index == rseg id */
179
 
        ulint           space,          /*!< in: space id */
180
 
        mtr_t*          mtr)            /*!< in: mtr */
181
 
{
182
 
        ut_ad(mutex_own(&(kernel_mutex)));
183
 
        ut_ad(sys_header);
184
 
        ut_ad(i < TRX_SYS_N_RSEGS);
185
 
 
186
 
        mlog_write_ulint(sys_header + TRX_SYS_RSEGS
187
 
                         + i * TRX_SYS_RSEG_SLOT_SIZE
188
 
                         + TRX_SYS_RSEG_SPACE,
189
 
                         space,
190
 
                         MLOG_4BYTES, mtr);
191
 
}
192
 
 
193
 
/*****************************************************************//**
194
 
Sets the page number of the nth rollback segment slot in the trx system
195
 
header. */
196
 
UNIV_INLINE
197
 
void
198
 
trx_sysf_rseg_set_page_no(
199
 
/*======================*/
200
 
        trx_sysf_t*     sys_header,     /*!< in: trx sys header */
201
 
        ulint           i,              /*!< in: slot index == rseg id */
202
 
        ulint           page_no,        /*!< in: page number, FIL_NULL if the
203
 
                                        slot is reset to unused */
204
 
        mtr_t*          mtr)            /*!< in: mtr */
205
 
{
206
 
        ut_ad(mutex_own(&(kernel_mutex)));
207
 
        ut_ad(sys_header);
208
 
        ut_ad(i < TRX_SYS_N_RSEGS);
209
 
 
210
 
        mlog_write_ulint(sys_header + TRX_SYS_RSEGS
211
 
                         + i * TRX_SYS_RSEG_SLOT_SIZE
212
 
                         + TRX_SYS_RSEG_PAGE_NO,
213
 
                         page_no,
214
 
                         MLOG_4BYTES, mtr);
215
 
}
216
 
#endif /* !UNIV_HOTBACKUP */
217
 
 
218
 
/*****************************************************************//**
219
 
Writes a trx id to an index page. In case that the id size changes in
220
 
some future version, this function should be used instead of
221
 
mach_write_... */
222
 
UNIV_INLINE
223
 
void
224
 
trx_write_trx_id(
225
 
/*=============*/
226
 
        byte*           ptr,    /*!< in: pointer to memory where written */
227
 
        trx_id_t        id)     /*!< in: id */
228
 
{
229
 
#if DATA_TRX_ID_LEN != 6
230
 
# error "DATA_TRX_ID_LEN != 6"
231
 
#endif
232
 
        mach_write_to_6(ptr, id);
233
 
}
234
 
 
235
 
#ifndef UNIV_HOTBACKUP
236
 
/*****************************************************************//**
237
 
Reads a trx id from an index page. In case that the id size changes in
238
 
some future version, this function should be used instead of
239
 
mach_read_...
240
 
@return id */
241
 
UNIV_INLINE
242
 
trx_id_t
243
 
trx_read_trx_id(
244
 
/*============*/
245
 
        const byte*     ptr)    /*!< in: pointer to memory from where to read */
246
 
{
247
 
#if DATA_TRX_ID_LEN != 6
248
 
# error "DATA_TRX_ID_LEN != 6"
249
 
#endif
250
 
        return(mach_read_from_6(ptr));
251
 
}
252
 
 
253
 
/****************************************************************//**
254
 
Looks for the trx handle with the given id in trx_list.
255
 
@return the trx handle or NULL if not found */
256
 
UNIV_INLINE
257
 
trx_t*
258
 
trx_get_on_id(
259
 
/*==========*/
260
 
        trx_id_t        trx_id) /*!< in: trx id to search for */
261
 
{
262
 
        trx_t*  trx;
263
 
 
264
 
        ut_ad(mutex_own(&(kernel_mutex)));
265
 
 
266
 
        trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
267
 
 
268
 
        while (trx != NULL) {
269
 
                if (trx_id == trx->id) {
270
 
 
271
 
                        return(trx);
272
 
                }
273
 
 
274
 
                trx = UT_LIST_GET_NEXT(trx_list, trx);
275
 
        }
276
 
 
277
 
        return(NULL);
278
 
}
279
 
 
280
 
/****************************************************************//**
281
 
Returns the minumum trx id in trx list. This is the smallest id for which
282
 
the trx can possibly be active. (But, you must look at the trx->conc_state to
283
 
find out if the minimum trx id transaction itself is active, or already
284
 
committed.)
285
 
@return the minimum trx id, or trx_sys->max_trx_id if the trx list is empty */
286
 
UNIV_INLINE
287
 
trx_id_t
288
 
trx_list_get_min_trx_id(void)
289
 
/*=========================*/
290
 
{
291
 
        trx_t*  trx;
292
 
 
293
 
        ut_ad(mutex_own(&(kernel_mutex)));
294
 
 
295
 
        trx = UT_LIST_GET_LAST(trx_sys->trx_list);
296
 
 
297
 
        if (trx == NULL) {
298
 
 
299
 
                return(trx_sys->max_trx_id);
300
 
        }
301
 
 
302
 
        return(trx->id);
303
 
}
304
 
 
305
 
/****************************************************************//**
306
 
Checks if a transaction with the given id is active.
307
 
@return TRUE if active */
308
 
UNIV_INLINE
309
 
ibool
310
 
trx_is_active(
311
 
/*==========*/
312
 
        trx_id_t        trx_id) /*!< in: trx id of the transaction */
313
 
{
314
 
        trx_t*  trx;
315
 
 
316
 
        ut_ad(mutex_own(&(kernel_mutex)));
317
 
 
318
 
        if (trx_id < trx_list_get_min_trx_id()) {
319
 
 
320
 
                return(FALSE);
321
 
        }
322
 
 
323
 
        if (UNIV_UNLIKELY(trx_id >= trx_sys->max_trx_id)) {
324
 
 
325
 
                /* There must be corruption: we return TRUE because this
326
 
                function is only called by lock_clust_rec_some_has_impl()
327
 
                and row_vers_impl_x_locked_off_kernel() and they have
328
 
                diagnostic prints in this case */
329
 
 
330
 
                return(TRUE);
331
 
        }
332
 
 
333
 
        trx = trx_get_on_id(trx_id);
334
 
        if (trx && (trx->conc_state == TRX_ACTIVE
335
 
                    || trx->conc_state == TRX_PREPARED)) {
336
 
 
337
 
                return(TRUE);
338
 
        }
339
 
 
340
 
        return(FALSE);
341
 
}
342
 
 
343
 
/*****************************************************************//**
344
 
Allocates a new transaction id.
345
 
@return new, allocated trx id */
346
 
UNIV_INLINE
347
 
trx_id_t
348
 
trx_sys_get_new_trx_id(void)
349
 
/*========================*/
350
 
{
351
 
        trx_id_t        id;
352
 
 
353
 
        ut_ad(mutex_own(&kernel_mutex));
354
 
 
355
 
        /* VERY important: after the database is started, max_trx_id value is
356
 
        divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the following if
357
 
        will evaluate to TRUE when this function is first time called,
358
 
        and the value for trx id will be written to disk-based header!
359
 
        Thus trx id values will not overlap when the database is
360
 
        repeatedly started! */
361
 
 
362
 
        if ((ulint) trx_sys->max_trx_id % TRX_SYS_TRX_ID_WRITE_MARGIN == 0) {
363
 
 
364
 
                trx_sys_flush_max_trx_id();
365
 
        }
366
 
 
367
 
        id = trx_sys->max_trx_id++;
368
 
 
369
 
        return(id);
370
 
}
371
 
 
372
 
/*****************************************************************//**
373
 
Allocates a new transaction number.
374
 
@return new, allocated trx number */
375
 
UNIV_INLINE
376
 
trx_id_t
377
 
trx_sys_get_new_trx_no(void)
378
 
/*========================*/
379
 
{
380
 
        ut_ad(mutex_own(&kernel_mutex));
381
 
 
382
 
        return(trx_sys_get_new_trx_id());
383
 
}
384
 
#endif /* !UNIV_HOTBACKUP */