Drizzled Public API Documentation

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