Drizzled Public API Documentation

trx0rseg.cc
1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2011, Oracle Corpn. 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 /**************************************************/
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 /******************************************************************/
45 UNIV_INTERN
48 /*===============*/
49  ulint id)
50 {
51  trx_rseg_t* rseg;
52 
53  ut_a(id < TRX_SYS_N_RSEGS);
54 
55  rseg = trx_sys->rseg_array[id];
56 
57  ut_a(rseg == NULL || id == rseg->id);
58 
59  return(rseg);
60 }
61 
62 /****************************************************************/
66 UNIV_INTERN
67 ulint
69 /*===================*/
70  ulint space,
71  ulint zip_size,
73  ulint max_size,
74  ulint rseg_slot_no,
75  mtr_t* 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 /***********************************************************************/
133 UNIV_INTERN
134 void
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  if (! srv_apply_log_only) {
144  /* There can't be any active transactions. */
145  ut_a(UT_LIST_GET_LEN(rseg->update_undo_list) == 0);
146  ut_a(UT_LIST_GET_LEN(rseg->insert_undo_list) == 0);
147  }
148 
149  undo = UT_LIST_GET_FIRST(rseg->update_undo_cached);
150 
151  while (undo != NULL) {
152  trx_undo_t* prev_undo = undo;
153 
154  undo = UT_LIST_GET_NEXT(undo_list, undo);
155  UT_LIST_REMOVE(undo_list, rseg->update_undo_cached, prev_undo);
156 
157  trx_undo_mem_free(prev_undo);
158  }
159 
160  undo = UT_LIST_GET_FIRST(rseg->insert_undo_cached);
161 
162  while (undo != NULL) {
163  trx_undo_t* prev_undo = undo;
164 
165  undo = UT_LIST_GET_NEXT(undo_list, undo);
166  UT_LIST_REMOVE(undo_list, rseg->insert_undo_cached, prev_undo);
167 
168  trx_undo_mem_free(prev_undo);
169  }
170 
171  trx_sys_set_nth_rseg(trx_sys, rseg->id, NULL);
172 
173  mem_free(rseg);
174 }
175 
176 /***************************************************************************
177 Creates and initializes a rollback segment object. The values for the
178 fields are read from the header. The object is inserted to the rseg
179 list of the trx system object and a pointer is inserted in the rseg
180 array in the trx system object.
181 @return own: rollback segment object */
182 static
183 trx_rseg_t*
184 trx_rseg_mem_create(
185 /*================*/
186  ulint id,
187  ulint space,
189  ulint zip_size,
191  ulint page_no,
193  ib_bh_t* ib_bh,
194  mtr_t* mtr)
195 {
196  ulint len;
197  trx_rseg_t* rseg;
198  fil_addr_t node_addr;
199  trx_rsegf_t* rseg_header;
200  trx_ulogf_t* undo_log_hdr;
201  ulint sum_of_undo_sizes;
202 
203  ut_ad(mutex_own(&kernel_mutex));
204 
205  void *rseg_buf= mem_zalloc(sizeof(trx_rseg_t));
206  rseg = static_cast<trx_rseg_t *>(rseg_buf);
207 
208  rseg->id = id;
209  rseg->space = space;
210  rseg->zip_size = zip_size;
211  rseg->page_no = page_no;
212 
213  mutex_create(rseg_mutex_key, &rseg->mutex, SYNC_RSEG);
214 
215  UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg);
216 
217  trx_sys_set_nth_rseg(trx_sys, id, rseg);
218 
219  rseg_header = trx_rsegf_get_new(space, zip_size, page_no, mtr);
220 
221  rseg->max_size = mtr_read_ulint(rseg_header + TRX_RSEG_MAX_SIZE,
222  MLOG_4BYTES, mtr);
223 
224  /* Initialize the undo log lists according to the rseg header */
225 
226  sum_of_undo_sizes = trx_undo_lists_init(rseg);
227 
228  rseg->curr_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
229  MLOG_4BYTES, mtr)
230  + 1 + sum_of_undo_sizes;
231 
232  len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr);
233  if (len > 0) {
234  const void* ptr;
235  rseg_queue_t rseg_queue;
236 
237  trx_sys->rseg_history_len += len;
238 
239  node_addr = trx_purge_get_log_from_hist(
240  flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
241  rseg->last_page_no = node_addr.page;
242  rseg->last_offset = node_addr.boffset;
243 
244  undo_log_hdr = trx_undo_page_get(rseg->space, rseg->zip_size,
245  node_addr.page,
246  mtr) + node_addr.boffset;
247 
249  undo_log_hdr + TRX_UNDO_TRX_NO);
251  undo_log_hdr + TRX_UNDO_DEL_MARKS, MLOG_2BYTES, mtr);
252 
253  rseg_queue.rseg = rseg;
254  rseg_queue.trx_no = rseg->last_trx_no;
255 
256  if (rseg->last_page_no != FIL_NULL) {
257  /* There is no need to cover this operation by the purge
258  mutex because we are still bootstrapping. */
259 
260  ptr = ib_bh_push(ib_bh, &rseg_queue);
261  ut_a(ptr != NULL);
262  }
263  } else {
264  rseg->last_page_no = FIL_NULL;
265  }
266 
267  return(rseg);
268 }
269 
270 /********************************************************************
271 Creates the memory copies for the rollback segments and initializes the
272 rseg list and array in trx_sys at a database startup. */
273 static
274 void
275 trx_rseg_create_instance(
276 /*=====================*/
277  trx_sysf_t* sys_header,
278  ib_bh_t* ib_bh,
279  mtr_t* mtr)
280 {
281  ulint i;
282 
283  for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
284  ulint page_no;
285 
286  page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
287 
288  if (page_no == FIL_NULL) {
289  trx_sys_set_nth_rseg(trx_sys, i, NULL);
290  } else {
291  ulint space;
292  ulint zip_size;
293  trx_rseg_t* rseg = NULL;
294 
296 
297  space = trx_sysf_rseg_get_space(sys_header, i, mtr);
298 
299  zip_size = space ? fil_space_get_zip_size(space) : 0;
300 
301  rseg = trx_rseg_mem_create(
302  i, space, zip_size, page_no, ib_bh, mtr);
303 
304  ut_a(rseg->id == i);
305  }
306  }
307 }
308 
309 /*********************************************************************
310 Creates a rollback segment.
311 @return pointer to new rollback segment if create successful */
312 UNIV_INTERN
313 trx_rseg_t*
314 trx_rseg_create(void)
315 /*=================*/
316 {
317  mtr_t mtr;
318  ulint slot_no;
319  trx_rseg_t* rseg = NULL;
320 
321  mtr_start(&mtr);
322 
323  /* To obey the latching order, acquire the file space
324  x-latch before the kernel mutex. */
325  mtr_x_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), &mtr);
326 
327  mutex_enter(&kernel_mutex);
328 
329  slot_no = trx_sysf_rseg_find_free(&mtr);
330 
331  if (slot_no != ULINT_UNDEFINED) {
332  ulint space;
333  ulint page_no;
334  ulint zip_size;
335  trx_sysf_t* sys_header;
336 
337  page_no = trx_rseg_header_create(
338  TRX_SYS_SPACE, 0, ULINT_MAX, slot_no, &mtr);
339 
340  ut_a(page_no != FIL_NULL);
341 
342  ut_ad(!trx_rseg_get_on_id(slot_no));
343 
344  sys_header = trx_sysf_get(&mtr);
345 
346  space = trx_sysf_rseg_get_space(sys_header, slot_no, &mtr);
347 
348  zip_size = space ? fil_space_get_zip_size(space) : 0;
349 
350  rseg = trx_rseg_mem_create(
351  slot_no, space, zip_size, page_no,
352  purge_sys->ib_bh, &mtr);
353  }
354 
355  mutex_exit(&kernel_mutex);
356  mtr_commit(&mtr);
357 
358  return(rseg);
359 }
360 
361 /********************************************************************
362 Initialize the rollback instance list. */
363 UNIV_INTERN
364 void
366 /*=========================*/
367  trx_sysf_t* sys_header,
368  ib_bh_t* ib_bh,
369  mtr_t* mtr)
370 {
371  UT_LIST_INIT(trx_sys->rseg_list);
372 
374 
375  trx_rseg_create_instance(sys_header, ib_bh, mtr);
376 }
377 
#define UT_LIST_GET_LEN(BASE)
Definition: ut0lst.h:217
trx_sys_t * trx_sys
Definition: trx0sys.cc:61
UNIV_INLINE ulint trx_sysf_rseg_get_space(trx_sysf_t *sys_header, ulint i, mtr_t *mtr)
trx_id_t trx_no
Definition: trx0rseg.h:188
#define UT_LIST_GET_NEXT(NAME, N)
Definition: ut0lst.h:201
UNIV_INLINE trx_sysf_t * trx_sysf_get(mtr_t *mtr)
UNIV_INLINE fil_addr_t flst_get_last(const flst_base_node_t *base, mtr_t *mtr)
UNIV_INTERN trx_rseg_t * trx_rseg_get_on_id(ulint id)
Definition: trx0rseg.cc:47
byte trx_ulogf_t
Definition: trx0types.h:107
#define mem_free(PTR)
Definition: mem0mem.h:249
UNIV_INTERN void trx_rseg_list_and_array_init(trx_sysf_t *sys_header, ib_bh_t *ib_bh, mtr_t *mtr)
Definition: trx0rseg.cc:365
trx_rseg_t * rseg
Definition: trx0rseg.h:189
UNIV_INTERN void trx_undo_mem_free(trx_undo_t *undo)
Definition: trx0undo.cc:1529
UNIV_INTERN void mlog_write_ulint(byte *ptr, ulint val, byte type, mtr_t *mtr)
Definition: mtr0log.cc:247
UNIV_INLINE void flst_init(flst_base_node_t *base, mtr_t *mtr)
UNIV_INTERN ulint fil_space_get_zip_size(ulint id)
Definition: fil0fil.cc:1535
UNIV_INLINE void trx_sys_set_nth_rseg(trx_sys_t *sys, ulint n, trx_rseg_t *rseg)
mutex_t mutex
Definition: trx0rseg.h:146
UNIV_INLINE void trx_sysf_rseg_set_page_no(trx_sysf_t *sys_header, ulint i, ulint page_no, mtr_t *mtr)
UNIV_INTERN rw_lock_t * fil_space_get_latch(ulint id, ulint *zip_size)
Definition: fil0fil.cc:515
ulint boffset
Definition: fil0fil.h:68
UNIV_INLINE trx_rsegf_t * trx_rsegf_get_new(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
#define mem_zalloc(N)
Definition: mem0mem.h:225
ib_bh_t * ib_bh
Definition: trx0purge.h:185
UNIV_INLINE ulint buf_block_get_page_no(const buf_block_t *block) __attribute__((pure))
UNIV_INTERN void mtr_commit(mtr_t *mtr) __attribute__((nonnull))
Definition: mtr0mtr.cc:247
#define UT_LIST_REMOVE(NAME, BASE, N)
Definition: ut0lst.h:178
UNIV_INTERN ulint mtr_read_ulint(const byte *ptr, ulint type, mtr_t *mtr)
Definition: mtr0mtr.cc:362
UNIV_INLINE fil_addr_t trx_purge_get_log_from_hist(fil_addr_t node_addr)
UNIV_INLINE page_t * trx_undo_page_get(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
UNIV_INTERN ulint trx_rseg_header_create(ulint space, ulint zip_size, ulint max_size, ulint rseg_slot_no, mtr_t *mtr)
Definition: trx0rseg.cc:68
UNIV_INTERN void * ib_bh_push(ib_bh_t *ib_bh, const void *elem)
Definition: ut0bh.cc:83
#define MLOG_2BYTES
Definition: mtr0mtr.h:74
ulint last_offset
Definition: trx0rseg.h:174
#define ut_a(EXPR)
Definition: ut0dbg.h:105
ulint rseg_history_len
Definition: trx0sys.h:599
#define UT_LIST_ADD_LAST(NAME, BASE, N)
Definition: ut0lst.h:119
#define UT_LIST_GET_FIRST(BASE)
Definition: ut0lst.h:224
#define MLOG_4BYTES
Definition: mtr0mtr.h:75
UNIV_INTERN ulint trx_sysf_rseg_find_free(mtr_t *mtr)
Definition: trx0sys.cc:718
UNIV_INTERN buf_block_t * fseg_create(ulint space, ulint page, ulint byte_offset, mtr_t *mtr)
Definition: fsp0fsp.cc:2351
#define ut_ad(EXPR)
Definition: ut0dbg.h:127
#define mtr_x_lock(B, MTR)
Definition: mtr0mtr.h:340
ibool last_del_marks
Definition: trx0rseg.h:178
#define UT_LIST_INIT(BASE)
Definition: ut0lst.h:84
#define FIL_NULL
Definition: fil0fil.h:48
trx_id_t last_trx_no
Definition: trx0rseg.h:176
UNIV_INLINE ulint trx_sysf_rseg_get_page_no(trx_sysf_t *sys_header, ulint i, mtr_t *mtr)
trx_purge_t * purge_sys
Definition: trx0purge.cc:48
#define TRX_UNDO_TRX_NO
Definition: trx0undo.h:498
UNIV_INLINE void trx_sysf_rseg_set_space(trx_sysf_t *sys_header, ulint i, ulint space, mtr_t *mtr)
UNIV_INTERN void trx_rseg_mem_free(trx_rseg_t *rseg)
Definition: trx0rseg.cc:135
ulint page
Definition: fil0fil.h:67
UNIV_INLINE void mtr_start(mtr_t *mtr) __attribute__((nonnull))
#define TRX_UNDO_DEL_MARKS
Definition: trx0undo.h:503
UNIV_INTERN ulint trx_undo_lists_init(trx_rseg_t *rseg)
Definition: trx0undo.cc:1382
UNIV_INLINE ib_uint64_t mach_read_from_8(const byte *b) __attribute__((nonnull
trx_rseg_t * rseg_array[TRX_SYS_N_RSEGS]
Definition: trx0sys.h:596
UNIV_INLINE ulint flst_get_len(const flst_base_node_t *base, mtr_t *mtr)
byte trx_rsegf_t
Definition: trx0types.h:103
byte trx_sysf_t
Definition: trx0types.h:101
UNIV_INLINE void trx_rsegf_set_nth_undo(trx_rsegf_t *rsegf, ulint n, ulint page_no, mtr_t *mtr)
ulint last_page_no
Definition: trx0rseg.h:171