Drizzled Public API Documentation

trx0undo.cc
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 /**************************************************/
26 #include "trx0undo.h"
27 
28 #ifdef UNIV_NONINL
29 #include "trx0undo.ic"
30 #endif
31 
32 #include "fsp0fsp.h"
33 #ifndef UNIV_HOTBACKUP
34 #include "mach0data.h"
35 #include "mtr0log.h"
36 #include "trx0rseg.h"
37 #include "trx0trx.h"
38 #include "srv0srv.h"
39 #include "trx0rec.h"
40 #include "trx0purge.h"
41 
42 /* How should the old versions in the history list be managed?
43  ----------------------------------------------------------
44 If each transaction is given a whole page for its update undo log, file
45 space consumption can be 10 times higher than necessary. Therefore,
46 partly filled update undo log pages should be reusable. But then there
47 is no way individual pages can be ordered so that the ordering agrees
48 with the serialization numbers of the transactions on the pages. Thus,
49 the history list must be formed of undo logs, not their header pages as
50 it was in the old implementation.
51  However, on a single header page the transactions are placed in
52 the order of their serialization numbers. As old versions are purged, we
53 may free the page when the last transaction on the page has been purged.
54  A problem is that the purge has to go through the transactions
55 in the serialization order. This means that we have to look through all
56 rollback segments for the one that has the smallest transaction number
57 in its history list.
58  When should we do a purge? A purge is necessary when space is
59 running out in any of the rollback segments. Then we may have to purge
60 also old version which might be needed by some consistent read. How do
61 we trigger the start of a purge? When a transaction writes to an undo log,
62 it may notice that the space is running out. When a read view is closed,
63 it may make some history superfluous. The server can have an utility which
64 periodically checks if it can purge some history.
65  In a parallellized purge we have the problem that a query thread
66 can remove a delete marked clustered index record before another query
67 thread has processed an earlier version of the record, which cannot then
68 be done because the row cannot be constructed from the clustered index
69 record. To avoid this problem, we will store in the update and delete mark
70 undo record also the columns necessary to construct the secondary index
71 entries which are modified.
72  We can latch the stack of versions of a single clustered index record
73 by taking a latch on the clustered index page. As long as the latch is held,
74 no new versions can be added and no versions removed by undo. But, a purge
75 can still remove old versions from the bottom of the stack. */
76 
77 /* How to protect rollback segments, undo logs, and history lists with
78  -------------------------------------------------------------------
79 latches?
80 -------
81 The contention of the kernel mutex should be minimized. When a transaction
82 does its first insert or modify in an index, an undo log is assigned for it.
83 Then we must have an x-latch to the rollback segment header.
84  When the transaction does more modifys or rolls back, the undo log is
85 protected with undo_mutex in the transaction.
86  When the transaction commits, its insert undo log is either reset and
87 cached for a fast reuse, or freed. In these cases we must have an x-latch on
88 the rollback segment page. The update undo log is put to the history list. If
89 it is not suitable for reuse, its slot in the rollback segment is reset. In
90 both cases, an x-latch must be acquired on the rollback segment.
91  The purge operation steps through the history list without modifying
92 it until a truncate operation occurs, which can remove undo logs from the end
93 of the list and release undo log segments. In stepping through the list,
94 s-latches on the undo log pages are enough, but in a truncate, x-latches must
95 be obtained on the rollback segment and individual pages. */
96 #endif /* !UNIV_HOTBACKUP */
97 
98 /********************************************************************/
100 static
101 void
102 trx_undo_page_init(
103 /*===============*/
104  page_t* undo_page,
105  ulint type,
106  mtr_t* mtr);
108 #ifndef UNIV_HOTBACKUP
109 /********************************************************************/
112 static
113 trx_undo_t*
114 trx_undo_mem_create(
115 /*================*/
116  trx_rseg_t* rseg,
117  ulint id,
118  ulint type,
120  trx_id_t trx_id,
122  const XID* xid,
123  ulint page_no,
124  ulint offset);
125 #endif /* !UNIV_HOTBACKUP */
126 /***************************************************************/
131 static
132 ulint
133 trx_undo_insert_header_reuse(
134 /*=========================*/
135  page_t* undo_page,
137  trx_id_t trx_id,
138  mtr_t* mtr);
139 /**********************************************************************/
142 static
143 void
144 trx_undo_discard_latest_update_undo(
145 /*================================*/
146  page_t* undo_page,
147  mtr_t* mtr);
149 #ifndef UNIV_HOTBACKUP
150 /***********************************************************************/
153 static
155 trx_undo_get_prev_rec_from_prev_page(
156 /*=================================*/
157  trx_undo_rec_t* rec,
158  ulint page_no,
159  ulint offset,
160  mtr_t* mtr)
161 {
162  ulint space;
163  ulint zip_size;
164  ulint prev_page_no;
165  page_t* prev_page;
166  page_t* undo_page;
167 
168  undo_page = page_align(rec);
169 
170  prev_page_no = flst_get_prev_addr(undo_page + TRX_UNDO_PAGE_HDR
171  + TRX_UNDO_PAGE_NODE, mtr)
172  .page;
173 
174  if (prev_page_no == FIL_NULL) {
175 
176  return(NULL);
177  }
178 
179  space = page_get_space_id(undo_page);
180  zip_size = fil_space_get_zip_size(space);
181 
182  prev_page = trx_undo_page_get_s_latched(space, zip_size,
183  prev_page_no, mtr);
184 
185  return(trx_undo_page_get_last_rec(prev_page, page_no, offset));
186 }
187 
188 /***********************************************************************/
191 UNIV_INTERN
194 /*==================*/
195  trx_undo_rec_t* rec,
196  ulint page_no,
197  ulint offset,
198  mtr_t* mtr)
199 {
200  trx_undo_rec_t* prev_rec;
201 
202  prev_rec = trx_undo_page_get_prev_rec(rec, page_no, offset);
203 
204  if (prev_rec) {
205 
206  return(prev_rec);
207  }
208 
209  /* We have to go to the previous undo log page to look for the
210  previous record */
211 
212  return(trx_undo_get_prev_rec_from_prev_page(rec, page_no, offset,
213  mtr));
214 }
215 
216 /***********************************************************************/
219 static
221 trx_undo_get_next_rec_from_next_page(
222 /*=================================*/
223  ulint space,
224  ulint zip_size,
226  page_t* undo_page,
227  ulint page_no,
228  ulint offset,
229  ulint mode,
230  mtr_t* mtr)
231 {
232  trx_ulogf_t* log_hdr;
233  ulint next_page_no;
234  page_t* next_page;
235  ulint next;
236 
237  if (page_no == page_get_page_no(undo_page)) {
238 
239  log_hdr = undo_page + offset;
240  next = mach_read_from_2(log_hdr + TRX_UNDO_NEXT_LOG);
241 
242  if (next != 0) {
243 
244  return(NULL);
245  }
246  }
247 
248  next_page_no = flst_get_next_addr(undo_page + TRX_UNDO_PAGE_HDR
249  + TRX_UNDO_PAGE_NODE, mtr)
250  .page;
251  if (next_page_no == FIL_NULL) {
252 
253  return(NULL);
254  }
255 
256  if (mode == RW_S_LATCH) {
257  next_page = trx_undo_page_get_s_latched(space, zip_size,
258  next_page_no, mtr);
259  } else {
260  ut_ad(mode == RW_X_LATCH);
261  next_page = trx_undo_page_get(space, zip_size,
262  next_page_no, mtr);
263  }
264 
265  return(trx_undo_page_get_first_rec(next_page, page_no, offset));
266 }
267 
268 /***********************************************************************/
271 UNIV_INTERN
274 /*==================*/
275  trx_undo_rec_t* rec,
276  ulint page_no,
277  ulint offset,
278  mtr_t* mtr)
279 {
280  ulint space;
281  ulint zip_size;
282  trx_undo_rec_t* next_rec;
283 
284  next_rec = trx_undo_page_get_next_rec(rec, page_no, offset);
285 
286  if (next_rec) {
287  return(next_rec);
288  }
289 
290  space = page_get_space_id(page_align(rec));
291  zip_size = fil_space_get_zip_size(space);
292 
293  return(trx_undo_get_next_rec_from_next_page(space, zip_size,
294  page_align(rec),
295  page_no, offset,
296  RW_S_LATCH, mtr));
297 }
298 
299 /***********************************************************************/
302 UNIV_INTERN
305 /*===================*/
306  ulint space,
307  ulint zip_size,
309  ulint page_no,
310  ulint offset,
311  ulint mode,
312  mtr_t* mtr)
313 {
314  page_t* undo_page;
315  trx_undo_rec_t* rec;
316 
317  if (mode == RW_S_LATCH) {
318  undo_page = trx_undo_page_get_s_latched(space, zip_size,
319  page_no, mtr);
320  } else {
321  undo_page = trx_undo_page_get(space, zip_size, page_no, mtr);
322  }
323 
324  rec = trx_undo_page_get_first_rec(undo_page, page_no, offset);
325 
326  if (rec) {
327  return(rec);
328  }
329 
330  return(trx_undo_get_next_rec_from_next_page(space, zip_size,
331  undo_page, page_no, offset,
332  mode, mtr));
333 }
334 
335 /*============== UNDO LOG FILE COPY CREATION AND FREEING ==================*/
336 
337 /**********************************************************************/
339 UNIV_INLINE
340 void
341 trx_undo_page_init_log(
342 /*===================*/
343  page_t* undo_page,
344  ulint type,
345  mtr_t* mtr)
346 {
348 
350 }
351 #else /* !UNIV_HOTBACKUP */
352 # define trx_undo_page_init_log(undo_page,type,mtr) ((void) 0)
353 #endif /* !UNIV_HOTBACKUP */
354 
355 /***********************************************************/
358 UNIV_INTERN
359 byte*
361 /*=====================*/
362  byte* ptr,
363  byte* end_ptr,
364  page_t* page,
365  mtr_t* mtr)
366 {
367  ulint type;
368 
369  ptr = mach_parse_compressed(ptr, end_ptr, &type);
370 
371  if (ptr == NULL) {
372 
373  return(NULL);
374  }
375 
376  if (page) {
377  trx_undo_page_init(page, type, mtr);
378  }
379 
380  return(ptr);
381 }
382 
383 /********************************************************************/
385 static
386 void
387 trx_undo_page_init(
388 /*===============*/
389  page_t* undo_page,
390  ulint type,
391  mtr_t* mtr)
392 {
393  trx_upagef_t* page_hdr;
394 
395  page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
396 
397  mach_write_to_2(page_hdr + TRX_UNDO_PAGE_TYPE, type);
398 
400  TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
402  TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
403 
405 
406  trx_undo_page_init_log(undo_page, type, mtr);
407 }
408 
409 #ifndef UNIV_HOTBACKUP
410 /***************************************************************/
414 static
415 ulint
416 trx_undo_seg_create(
417 /*================*/
418  trx_rseg_t* /*rseg*/,
419  trx_rsegf_t* rseg_hdr,
421  ulint type,
423  ulint* id,
424  page_t** undo_page,
427  mtr_t* mtr)
428 {
429  ulint slot_no;
430  ulint space;
431  buf_block_t* block;
432  trx_upagef_t* page_hdr;
433  trx_usegf_t* seg_hdr;
434  ulint n_reserved;
435  ibool success;
436  ulint err = DB_SUCCESS;
437 
438  ut_ad(mtr && id && rseg_hdr);
439  ut_ad(mutex_own(&(rseg->mutex)));
440 
441  /* fputs(type == TRX_UNDO_INSERT
442  ? "Creating insert undo log segment\n"
443  : "Creating update undo log segment\n", stderr); */
444  slot_no = trx_rsegf_undo_find_free(rseg_hdr, mtr);
445 
446  if (slot_no == ULINT_UNDEFINED) {
447  ut_print_timestamp(stderr);
448  fprintf(stderr,
449  " InnoDB: Warning: cannot find a free slot for"
450  " an undo log. Do you have too\n"
451  "InnoDB: many active transactions"
452  " running concurrently?\n");
453 
454  return(DB_TOO_MANY_CONCURRENT_TRXS);
455  }
456 
457  space = page_get_space_id(page_align(rseg_hdr));
458 
459  success = fsp_reserve_free_extents(&n_reserved, space, 2, FSP_UNDO,
460  mtr);
461  if (!success) {
462 
463  return(DB_OUT_OF_FILE_SPACE);
464  }
465 
466  /* Allocate a new file segment for the undo log */
467  block = fseg_create_general(space, 0,
469  + TRX_UNDO_FSEG_HEADER, TRUE, mtr);
470 
471  fil_space_release_free_extents(space, n_reserved);
472 
473  if (block == NULL) {
474  /* No space left */
475 
476  return(DB_OUT_OF_FILE_SPACE);
477  }
478 
479  buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
480 
481  *undo_page = buf_block_get_frame(block);
482 
483  page_hdr = *undo_page + TRX_UNDO_PAGE_HDR;
484  seg_hdr = *undo_page + TRX_UNDO_SEG_HDR;
485 
486  trx_undo_page_init(*undo_page, type, mtr);
487 
489  TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE,
490  MLOG_2BYTES, mtr);
491 
492  mlog_write_ulint(seg_hdr + TRX_UNDO_LAST_LOG, 0, MLOG_2BYTES, mtr);
493 
494  flst_init(seg_hdr + TRX_UNDO_PAGE_LIST, mtr);
495 
497  page_hdr + TRX_UNDO_PAGE_NODE, mtr);
498 
499  trx_rsegf_set_nth_undo(rseg_hdr, slot_no,
500  page_get_page_no(*undo_page), mtr);
501  *id = slot_no;
502 
503  return(err);
504 }
505 
506 /**********************************************************************/
508 UNIV_INLINE
509 void
510 trx_undo_header_create_log(
511 /*=======================*/
512  const page_t* undo_page,
513  trx_id_t trx_id,
514  mtr_t* mtr)
515 {
517 
518  mlog_catenate_ull_compressed(mtr, trx_id);
519 }
520 #else /* !UNIV_HOTBACKUP */
521 # define trx_undo_header_create_log(undo_page,trx_id,mtr) ((void) 0)
522 #endif /* !UNIV_HOTBACKUP */
523 
524 /***************************************************************/
529 static
530 ulint
531 trx_undo_header_create(
532 /*===================*/
533  page_t* undo_page,
538  trx_id_t trx_id,
539  mtr_t* mtr)
540 {
541  trx_upagef_t* page_hdr;
542  trx_usegf_t* seg_hdr;
543  trx_ulogf_t* log_hdr;
544  trx_ulogf_t* prev_log_hdr;
545  ulint prev_log;
546  ulint free;
547  ulint new_free;
548 
549  ut_ad(mtr && undo_page);
550 
551  page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
552  seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
553 
554  free = mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE);
555 
556  log_hdr = undo_page + free;
557 
558  new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE;
559 
560  ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < UNIV_PAGE_SIZE - 100);
561 
562  mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free);
563 
564  mach_write_to_2(page_hdr + TRX_UNDO_PAGE_FREE, new_free);
565 
566  mach_write_to_2(seg_hdr + TRX_UNDO_STATE, TRX_UNDO_ACTIVE);
567 
568  prev_log = mach_read_from_2(seg_hdr + TRX_UNDO_LAST_LOG);
569 
570  if (prev_log != 0) {
571  prev_log_hdr = undo_page + prev_log;
572 
573  mach_write_to_2(prev_log_hdr + TRX_UNDO_NEXT_LOG, free);
574  }
575 
576  mach_write_to_2(seg_hdr + TRX_UNDO_LAST_LOG, free);
577 
578  log_hdr = undo_page + free;
579 
580  mach_write_to_2(log_hdr + TRX_UNDO_DEL_MARKS, TRUE);
581 
582  mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
583  mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
584 
585  mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
586  mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
587 
588  mach_write_to_2(log_hdr + TRX_UNDO_NEXT_LOG, 0);
589  mach_write_to_2(log_hdr + TRX_UNDO_PREV_LOG, prev_log);
590 
591  /* Write the log record about the header creation */
592  trx_undo_header_create_log(undo_page, trx_id, mtr);
593 
594  return(free);
595 }
596 
597 #ifndef UNIV_HOTBACKUP
598 /********************************************************************/
600 static
601 void
602 trx_undo_write_xid(
603 /*===============*/
604  trx_ulogf_t* log_hdr,
605  const XID* xid,
606  mtr_t* mtr)
607 {
609  (ulint)xid->formatID, MLOG_4BYTES, mtr);
610 
612  (ulint)xid->gtrid_length, MLOG_4BYTES, mtr);
613 
615  (ulint)xid->bqual_length, MLOG_4BYTES, mtr);
616 
617  mlog_write_string(log_hdr + TRX_UNDO_XA_XID, (const byte*) xid->data,
618  XIDDATASIZE, mtr);
619 }
620 
621 /********************************************************************/
623 static
624 void
625 trx_undo_read_xid(
626 /*==============*/
627  trx_ulogf_t* log_hdr,
628  XID* xid)
629 {
630  xid->formatID = (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT);
631 
632  xid->gtrid_length
633  = (long) mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN);
634  xid->bqual_length
635  = (long) mach_read_from_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN);
636 
637  memcpy(xid->data, log_hdr + TRX_UNDO_XA_XID, XIDDATASIZE);
638 }
639 
640 /***************************************************************/
642 static
643 void
644 trx_undo_header_add_space_for_xid(
645 /*==============================*/
646  page_t* undo_page,
647  trx_ulogf_t* log_hdr,
648  mtr_t* mtr)
649 {
650  trx_upagef_t* page_hdr;
651  ulint free;
652  ulint new_free;
653 
654  page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
655 
656  free = mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE);
657 
658  /* free is now the end offset of the old style undo log header */
659 
660  ut_a(free == (ulint)(log_hdr - undo_page) + TRX_UNDO_LOG_OLD_HDR_SIZE);
661 
662  new_free = free + (TRX_UNDO_LOG_XA_HDR_SIZE
664 
665  /* Add space for a XID after the header, update the free offset
666  fields on the undo log page and in the undo log header */
667 
668  mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_START, new_free,
669  MLOG_2BYTES, mtr);
670 
671  mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_FREE, new_free,
672  MLOG_2BYTES, mtr);
673 
674  mlog_write_ulint(log_hdr + TRX_UNDO_LOG_START, new_free,
675  MLOG_2BYTES, mtr);
676 }
677 
678 /**********************************************************************/
680 UNIV_INLINE
681 void
682 trx_undo_insert_header_reuse_log(
683 /*=============================*/
684  const page_t* undo_page,
685  trx_id_t trx_id,
686  mtr_t* mtr)
687 {
689 
690  mlog_catenate_ull_compressed(mtr, trx_id);
691 }
692 #else /* !UNIV_HOTBACKUP */
693 # define trx_undo_insert_header_reuse_log(undo_page,trx_id,mtr) ((void) 0)
694 #endif /* !UNIV_HOTBACKUP */
695 
696 /***********************************************************/
699 UNIV_INTERN
700 byte*
702 /*=======================*/
703  ulint type,
704  byte* ptr,
705  byte* end_ptr,
706  page_t* page,
707  mtr_t* mtr)
708 {
709  trx_id_t trx_id;
710  /* Silence a GCC warning about possibly uninitialized variable
711  when mach_ull_parse_compressed() is not inlined. */
712  ut_d(trx_id = 0);
713  /* Declare the variable uninitialized in Valgrind, so that the
714  above initialization will not mask any bugs. */
715  UNIV_MEM_INVALID(&trx_id, sizeof trx_id);
716 
717  ptr = mach_ull_parse_compressed(ptr, end_ptr, &trx_id);
718 
719  if (ptr == NULL) {
720 
721  return(NULL);
722  }
723 
724  if (page) {
725  if (type == MLOG_UNDO_HDR_CREATE) {
726  trx_undo_header_create(page, trx_id, mtr);
727  } else {
728  ut_ad(type == MLOG_UNDO_HDR_REUSE);
729  trx_undo_insert_header_reuse(page, trx_id, mtr);
730  }
731  }
732 
733  return(ptr);
734 }
735 
736 /***************************************************************/
741 static
742 ulint
743 trx_undo_insert_header_reuse(
744 /*=========================*/
745  page_t* undo_page,
747  trx_id_t trx_id,
748  mtr_t* mtr)
749 {
750  trx_upagef_t* page_hdr;
751  trx_usegf_t* seg_hdr;
752  trx_ulogf_t* log_hdr;
753  ulint free;
754  ulint new_free;
755 
756  ut_ad(mtr && undo_page);
757 
758  page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
759  seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
760 
761  free = TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE;
762 
763  ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < UNIV_PAGE_SIZE - 100);
764 
765  log_hdr = undo_page + free;
766 
767  new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE;
768 
769  /* Insert undo data is not needed after commit: we may free all
770  the space on the page */
771 
772  ut_a(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
774  == TRX_UNDO_INSERT);
775 
776  mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free);
777 
778  mach_write_to_2(page_hdr + TRX_UNDO_PAGE_FREE, new_free);
779 
780  mach_write_to_2(seg_hdr + TRX_UNDO_STATE, TRX_UNDO_ACTIVE);
781 
782  log_hdr = undo_page + free;
783 
784  mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
785  mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
786 
787  mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
788  mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
789 
790  /* Write the log record MLOG_UNDO_HDR_REUSE */
791  trx_undo_insert_header_reuse_log(undo_page, trx_id, mtr);
792 
793  return(free);
794 }
795 
796 #ifndef UNIV_HOTBACKUP
797 /**********************************************************************/
799 UNIV_INLINE
800 void
801 trx_undo_discard_latest_log(
802 /*========================*/
803  page_t* undo_page,
804  mtr_t* mtr)
805 {
807 }
808 #else /* !UNIV_HOTBACKUP */
809 # define trx_undo_discard_latest_log(undo_page, mtr) ((void) 0)
810 #endif /* !UNIV_HOTBACKUP */
811 
812 /***********************************************************/
815 UNIV_INTERN
816 byte*
818 /*==========================*/
819  byte* ptr,
820  byte* /*end_ptr*/,
821  page_t* page,
822  mtr_t* mtr)
823 {
824  ut_ad(end_ptr);
825 
826  if (page) {
827  trx_undo_discard_latest_update_undo(page, mtr);
828  }
829 
830  return(ptr);
831 }
832 
833 /**********************************************************************/
836 static
837 void
838 trx_undo_discard_latest_update_undo(
839 /*================================*/
840  page_t* undo_page,
841  mtr_t* mtr)
842 {
843  trx_usegf_t* seg_hdr;
844  trx_upagef_t* page_hdr;
845  trx_ulogf_t* log_hdr;
846  trx_ulogf_t* prev_log_hdr;
847  ulint free;
848  ulint prev_hdr_offset;
849 
850  seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
851  page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
852 
853  free = mach_read_from_2(seg_hdr + TRX_UNDO_LAST_LOG);
854  log_hdr = undo_page + free;
855 
856  prev_hdr_offset = mach_read_from_2(log_hdr + TRX_UNDO_PREV_LOG);
857 
858  if (prev_hdr_offset != 0) {
859  prev_log_hdr = undo_page + prev_hdr_offset;
860 
862  mach_read_from_2(prev_log_hdr
863  + TRX_UNDO_LOG_START));
864  mach_write_to_2(prev_log_hdr + TRX_UNDO_NEXT_LOG, 0);
865  }
866 
867  mach_write_to_2(page_hdr + TRX_UNDO_PAGE_FREE, free);
868 
869  mach_write_to_2(seg_hdr + TRX_UNDO_STATE, TRX_UNDO_CACHED);
870  mach_write_to_2(seg_hdr + TRX_UNDO_LAST_LOG, prev_hdr_offset);
871 
872  trx_undo_discard_latest_log(undo_page, mtr);
873 }
874 
875 #ifndef UNIV_HOTBACKUP
876 /********************************************************************/
879 UNIV_INTERN
880 ulint
882 /*==============*/
883  trx_t* trx,
884  trx_undo_t* undo,
885  mtr_t* mtr)
888 {
889  page_t* header_page;
890  page_t* new_page;
891  trx_rseg_t* rseg;
892  ulint page_no;
893  ulint n_reserved;
894  ibool success;
895 
896  ut_ad(mutex_own(&(trx->undo_mutex)));
897  ut_ad(!mutex_own(&kernel_mutex));
898  ut_ad(mutex_own(&(trx->rseg->mutex)));
899 
900  rseg = trx->rseg;
901 
902  if (rseg->curr_size == rseg->max_size) {
903 
904  return(FIL_NULL);
905  }
906 
907  header_page = trx_undo_page_get(undo->space, undo->zip_size,
908  undo->hdr_page_no, mtr);
909 
910  success = fsp_reserve_free_extents(&n_reserved, undo->space, 1,
911  FSP_UNDO, mtr);
912  if (!success) {
913 
914  return(FIL_NULL);
915  }
916 
917  page_no = fseg_alloc_free_page_general(header_page + TRX_UNDO_SEG_HDR
919  undo->top_page_no + 1, FSP_UP,
920  TRUE, mtr);
921 
922  fil_space_release_free_extents(undo->space, n_reserved);
923 
924  if (page_no == FIL_NULL) {
925 
926  /* No space left */
927 
928  return(FIL_NULL);
929  }
930 
931  undo->last_page_no = page_no;
932 
933  new_page = trx_undo_page_get(undo->space, undo->zip_size,
934  page_no, mtr);
935 
936  trx_undo_page_init(new_page, undo->type, mtr);
937 
938  flst_add_last(header_page + TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST,
939  new_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr);
940  undo->size++;
941  rseg->curr_size++;
942 
943  return(page_no);
944 }
945 
946 /********************************************************************/
949 static
950 ulint
951 trx_undo_free_page(
952 /*===============*/
953  trx_rseg_t* rseg,
954  ibool in_history,
956  ulint space,
957  ulint hdr_page_no,
958  ulint page_no,
960  mtr_t* mtr)
963 {
964  page_t* header_page;
965  page_t* undo_page;
966  fil_addr_t last_addr;
967  trx_rsegf_t* rseg_header;
968  ulint hist_size;
969  ulint zip_size;
970 
971  ut_a(hdr_page_no != page_no);
972  ut_ad(!mutex_own(&kernel_mutex));
973  ut_ad(mutex_own(&(rseg->mutex)));
974 
975  zip_size = rseg->zip_size;
976 
977  undo_page = trx_undo_page_get(space, zip_size, page_no, mtr);
978 
979  header_page = trx_undo_page_get(space, zip_size, hdr_page_no, mtr);
980 
981  flst_remove(header_page + TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST,
982  undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr);
983 
984  fseg_free_page(header_page + TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER,
985  space, page_no, mtr);
986 
987  last_addr = flst_get_last(header_page + TRX_UNDO_SEG_HDR
988  + TRX_UNDO_PAGE_LIST, mtr);
989  rseg->curr_size--;
990 
991  if (in_history) {
992  rseg_header = trx_rsegf_get(space, zip_size,
993  rseg->page_no, mtr);
994 
995  hist_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
996  MLOG_4BYTES, mtr);
997  ut_ad(hist_size > 0);
998  mlog_write_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
999  hist_size - 1, MLOG_4BYTES, mtr);
1000  }
1001 
1002  return(last_addr.page);
1003 }
1004 
1005 /********************************************************************/
1008 static
1009 void
1010 trx_undo_free_page_in_rollback(
1011 /*===========================*/
1012  trx_t* /*trx*/,
1013  trx_undo_t* undo,
1014  ulint page_no,
1016  mtr_t* mtr)
1019 {
1020  ulint last_page_no;
1021 
1022  ut_ad(undo->hdr_page_no != page_no);
1023  ut_ad(mutex_own(&(trx->undo_mutex)));
1024 
1025  last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space,
1026  undo->hdr_page_no, page_no, mtr);
1027 
1028  undo->last_page_no = last_page_no;
1029  undo->size--;
1030 }
1031 
1032 /********************************************************************/
1035 static
1036 void
1037 trx_undo_empty_header_page(
1038 /*=======================*/
1039  ulint space,
1040  ulint zip_size,
1042  ulint hdr_page_no,
1043  ulint hdr_offset,
1044  mtr_t* mtr)
1045 {
1046  page_t* header_page;
1047  trx_ulogf_t* log_hdr;
1048  ulint end;
1049 
1050  header_page = trx_undo_page_get(space, zip_size, hdr_page_no, mtr);
1051 
1052  log_hdr = header_page + hdr_offset;
1053 
1054  end = trx_undo_page_get_end(header_page, hdr_page_no, hdr_offset);
1055 
1056  mlog_write_ulint(log_hdr + TRX_UNDO_LOG_START, end, MLOG_2BYTES, mtr);
1057 }
1058 
1059 /***********************************************************************/
1062 UNIV_INTERN
1063 void
1065 /*==================*/
1066  trx_t* trx,
1067  trx_undo_t* undo,
1068  undo_no_t limit)
1070 {
1071  page_t* undo_page;
1072  ulint last_page_no;
1073  trx_undo_rec_t* rec;
1074  trx_undo_rec_t* trunc_here;
1075  mtr_t mtr;
1076 
1077  ut_ad(mutex_own(&(trx->undo_mutex)));
1078  ut_ad(mutex_own(&(trx->rseg->mutex)));
1079 
1080  for (;;) {
1081  mtr_start(&mtr);
1082 
1083  trunc_here = NULL;
1084 
1085  last_page_no = undo->last_page_no;
1086 
1087  undo_page = trx_undo_page_get(undo->space, undo->zip_size,
1088  last_page_no, &mtr);
1089 
1090  rec = trx_undo_page_get_last_rec(undo_page, undo->hdr_page_no,
1091  undo->hdr_offset);
1092  for (;;) {
1093  if (rec == NULL) {
1094  if (last_page_no == undo->hdr_page_no) {
1095 
1096  goto function_exit;
1097  }
1098 
1099  trx_undo_free_page_in_rollback(
1100  trx, undo, last_page_no, &mtr);
1101  break;
1102  }
1103 
1104  if (trx_undo_rec_get_undo_no(rec) >= limit) {
1105  /* Truncate at least this record off, maybe
1106  more */
1107  trunc_here = rec;
1108  } else {
1109  goto function_exit;
1110  }
1111 
1112  rec = trx_undo_page_get_prev_rec(rec,
1113  undo->hdr_page_no,
1114  undo->hdr_offset);
1115  }
1116 
1117  mtr_commit(&mtr);
1118  }
1119 
1120 function_exit:
1121  if (trunc_here) {
1122  mlog_write_ulint(undo_page + TRX_UNDO_PAGE_HDR
1124  trunc_here - undo_page, MLOG_2BYTES, &mtr);
1125  }
1126 
1127  mtr_commit(&mtr);
1128 }
1129 
1130 /***********************************************************************/
1133 UNIV_INTERN
1134 void
1136 /*====================*/
1137  trx_rseg_t* rseg,
1138  ulint space,
1139  ulint hdr_page_no,
1140  ulint hdr_offset,
1141  undo_no_t limit)
1148 {
1149  page_t* undo_page;
1150  trx_undo_rec_t* rec;
1151  trx_undo_rec_t* last_rec;
1152  ulint page_no;
1153  mtr_t mtr;
1154 
1155  ut_ad(mutex_own(&(rseg->mutex)));
1156 
1157  if (!limit) {
1158 
1159  return;
1160  }
1161 loop:
1162  mtr_start(&mtr);
1163 
1164  rec = trx_undo_get_first_rec(space, rseg->zip_size,
1165  hdr_page_no, hdr_offset,
1166  RW_X_LATCH, &mtr);
1167  if (rec == NULL) {
1168  /* Already empty */
1169 
1170  mtr_commit(&mtr);
1171 
1172  return;
1173  }
1174 
1175  undo_page = page_align(rec);
1176 
1177  last_rec = trx_undo_page_get_last_rec(undo_page, hdr_page_no,
1178  hdr_offset);
1179  if (trx_undo_rec_get_undo_no(last_rec) >= limit) {
1180 
1181  mtr_commit(&mtr);
1182 
1183  return;
1184  }
1185 
1186  page_no = page_get_page_no(undo_page);
1187 
1188  if (page_no == hdr_page_no) {
1189  trx_undo_empty_header_page(space, rseg->zip_size,
1190  hdr_page_no, hdr_offset,
1191  &mtr);
1192  } else {
1193  trx_undo_free_page(rseg, TRUE, space, hdr_page_no,
1194  page_no, &mtr);
1195  }
1196 
1197  mtr_commit(&mtr);
1198 
1199  goto loop;
1200 }
1201 
1202 /**********************************************************************/
1204 static
1205 void
1206 trx_undo_seg_free(
1207 /*==============*/
1208  trx_undo_t* undo)
1209 {
1210  trx_rseg_t* rseg;
1211  fseg_header_t* file_seg;
1212  trx_rsegf_t* rseg_header;
1213  trx_usegf_t* seg_header;
1214  ibool finished;
1215  mtr_t mtr;
1216 
1217  rseg = undo->rseg;
1218 
1219  do {
1220 
1221  mtr_start(&mtr);
1222 
1223  ut_ad(!mutex_own(&kernel_mutex));
1224 
1225  mutex_enter(&(rseg->mutex));
1226 
1227  seg_header = trx_undo_page_get(undo->space, undo->zip_size,
1228  undo->hdr_page_no,
1229  &mtr) + TRX_UNDO_SEG_HDR;
1230 
1231  file_seg = seg_header + TRX_UNDO_FSEG_HEADER;
1232 
1233  finished = fseg_free_step(file_seg, &mtr);
1234 
1235  if (finished) {
1236  /* Update the rseg header */
1237  rseg_header = trx_rsegf_get(
1238  rseg->space, rseg->zip_size, rseg->page_no,
1239  &mtr);
1240  trx_rsegf_set_nth_undo(rseg_header, undo->id, FIL_NULL,
1241  &mtr);
1242  }
1243 
1244  mutex_exit(&(rseg->mutex));
1245  mtr_commit(&mtr);
1246  } while (!finished);
1247 }
1248 
1249 /*========== UNDO LOG MEMORY COPY INITIALIZATION =====================*/
1250 
1251 /********************************************************************/
1256 static
1257 trx_undo_t*
1258 trx_undo_mem_create_at_db_start(
1259 /*============================*/
1260  trx_rseg_t* rseg,
1261  ulint id,
1262  ulint page_no,
1263  mtr_t* mtr)
1264 {
1265  page_t* undo_page;
1266  trx_upagef_t* page_header;
1267  trx_usegf_t* seg_header;
1268  trx_ulogf_t* undo_header;
1269  trx_undo_t* undo;
1270  ulint type;
1271  ulint state;
1272  trx_id_t trx_id;
1273  ulint offset;
1274  fil_addr_t last_addr;
1275  page_t* last_page;
1276  trx_undo_rec_t* rec;
1277  XID xid;
1278  ibool xid_exists = FALSE;
1279 
1280  if (id >= TRX_RSEG_N_SLOTS) {
1281  fprintf(stderr,
1282  "InnoDB: Error: undo->id is %lu\n", (ulong) id);
1283  ut_error;
1284  }
1285 
1286  undo_page = trx_undo_page_get(rseg->space, rseg->zip_size,
1287  page_no, mtr);
1288 
1289  page_header = undo_page + TRX_UNDO_PAGE_HDR;
1290 
1291  type = mtr_read_ulint(page_header + TRX_UNDO_PAGE_TYPE, MLOG_2BYTES,
1292  mtr);
1293  seg_header = undo_page + TRX_UNDO_SEG_HDR;
1294 
1295  state = mach_read_from_2(seg_header + TRX_UNDO_STATE);
1296 
1297  offset = mach_read_from_2(seg_header + TRX_UNDO_LAST_LOG);
1298 
1299  undo_header = undo_page + offset;
1300 
1301  trx_id = mach_read_from_8(undo_header + TRX_UNDO_TRX_ID);
1302 
1303  xid_exists = mtr_read_ulint(undo_header + TRX_UNDO_XID_EXISTS,
1304  MLOG_1BYTE, mtr);
1305 
1306  /* Read X/Open XA transaction identification if it exists, or
1307  set it to NULL. */
1308 
1309  memset(&xid, 0, sizeof(xid));
1310  xid.formatID = -1;
1311 
1312  if (xid_exists == TRUE) {
1313  trx_undo_read_xid(undo_header, &xid);
1314  }
1315 
1316  mutex_enter(&(rseg->mutex));
1317 
1318  undo = trx_undo_mem_create(rseg, id, type, trx_id, &xid,
1319  page_no, offset);
1320  mutex_exit(&(rseg->mutex));
1321 
1323  undo_header + TRX_UNDO_DICT_TRANS, MLOG_1BYTE, mtr);
1324 
1325  undo->table_id = mach_read_from_8(undo_header + TRX_UNDO_TABLE_ID);
1326  undo->state = state;
1327  undo->size = flst_get_len(seg_header + TRX_UNDO_PAGE_LIST, mtr);
1328 
1329  /* If the log segment is being freed, the page list is inconsistent! */
1330  if (state == TRX_UNDO_TO_FREE) {
1331 
1332  goto add_to_list;
1333  }
1334 
1335  last_addr = flst_get_last(seg_header + TRX_UNDO_PAGE_LIST, mtr);
1336 
1337  undo->last_page_no = last_addr.page;
1338  undo->top_page_no = last_addr.page;
1339 
1340  last_page = trx_undo_page_get(rseg->space, rseg->zip_size,
1341  undo->last_page_no, mtr);
1342 
1343  rec = trx_undo_page_get_last_rec(last_page, page_no, offset);
1344 
1345  if (rec == NULL) {
1346  undo->empty = TRUE;
1347  } else {
1348  undo->empty = FALSE;
1349  undo->top_offset = rec - last_page;
1351  }
1352 add_to_list:
1353  if (type == TRX_UNDO_INSERT) {
1354  if (state != TRX_UNDO_CACHED) {
1355  UT_LIST_ADD_LAST(undo_list, rseg->insert_undo_list,
1356  undo);
1357  } else {
1358  UT_LIST_ADD_LAST(undo_list, rseg->insert_undo_cached,
1359  undo);
1360  }
1361  } else {
1362  ut_ad(type == TRX_UNDO_UPDATE);
1363  if (state != TRX_UNDO_CACHED) {
1364  UT_LIST_ADD_LAST(undo_list, rseg->update_undo_list,
1365  undo);
1366  } else {
1367  UT_LIST_ADD_LAST(undo_list, rseg->update_undo_cached,
1368  undo);
1369  }
1370  }
1371 
1372  return(undo);
1373 }
1374 
1375 /********************************************************************/
1380 UNIV_INTERN
1381 ulint
1383 /*================*/
1384  trx_rseg_t* rseg)
1385 {
1386  ulint page_no;
1387  trx_undo_t* undo;
1388  ulint size = 0;
1389  trx_rsegf_t* rseg_header;
1390  ulint i;
1391  mtr_t mtr;
1392 
1393  UT_LIST_INIT(rseg->update_undo_list);
1394  UT_LIST_INIT(rseg->update_undo_cached);
1395  UT_LIST_INIT(rseg->insert_undo_list);
1396  UT_LIST_INIT(rseg->insert_undo_cached);
1397 
1398  mtr_start(&mtr);
1399 
1400  rseg_header = trx_rsegf_get_new(rseg->space, rseg->zip_size,
1401  rseg->page_no, &mtr);
1402 
1403  for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
1404  page_no = trx_rsegf_get_nth_undo(rseg_header, i, &mtr);
1405 
1406  /* In forced recovery: try to avoid operations which look
1407  at database pages; undo logs are rapidly changing data, and
1408  the probability that they are in an inconsistent state is
1409  high */
1410 
1411  if (page_no != FIL_NULL
1412  && srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) {
1413 
1414  undo = trx_undo_mem_create_at_db_start(rseg, i,
1415  page_no, &mtr);
1416  size += undo->size;
1417 
1418  mtr_commit(&mtr);
1419 
1420  mtr_start(&mtr);
1421 
1422  rseg_header = trx_rsegf_get(
1423  rseg->space, rseg->zip_size, rseg->page_no,
1424  &mtr);
1425  }
1426  }
1427 
1428  mtr_commit(&mtr);
1429 
1430  return(size);
1431 }
1432 
1433 /********************************************************************/
1436 static
1437 trx_undo_t*
1438 trx_undo_mem_create(
1439 /*================*/
1440  trx_rseg_t* rseg,
1441  ulint id,
1442  ulint type,
1444  trx_id_t trx_id,
1446  const XID* xid,
1447  ulint page_no,
1448  ulint offset)
1449 {
1450  trx_undo_t* undo;
1451 
1452  ut_ad(mutex_own(&(rseg->mutex)));
1453 
1454  if (id >= TRX_RSEG_N_SLOTS) {
1455  fprintf(stderr,
1456  "InnoDB: Error: undo->id is %lu\n", (ulong) id);
1457  ut_error;
1458  }
1459 
1460  undo = static_cast<trx_undo_t *>(mem_alloc(sizeof(trx_undo_t)));
1461 
1462  if (undo == NULL) {
1463 
1464  return NULL;
1465  }
1466 
1467  undo->id = id;
1468  undo->type = type;
1469  undo->state = TRX_UNDO_ACTIVE;
1470  undo->del_marks = FALSE;
1471  undo->trx_id = trx_id;
1472  undo->xid = *xid;
1473 
1474  undo->dict_operation = FALSE;
1475 
1476  undo->rseg = rseg;
1477 
1478  undo->space = rseg->space;
1479  undo->zip_size = rseg->zip_size;
1480  undo->hdr_page_no = page_no;
1481  undo->hdr_offset = offset;
1482  undo->last_page_no = page_no;
1483  undo->size = 1;
1484 
1485  undo->empty = TRUE;
1486  undo->top_page_no = page_no;
1487  undo->guess_block = NULL;
1488 
1489  return(undo);
1490 }
1491 
1492 /********************************************************************/
1494 static
1495 void
1496 trx_undo_mem_init_for_reuse(
1497 /*========================*/
1498  trx_undo_t* undo,
1499  trx_id_t trx_id,
1501  const XID* xid,
1502  ulint offset)
1503 {
1504  ut_ad(mutex_own(&((undo->rseg)->mutex)));
1505 
1506  if (UNIV_UNLIKELY(undo->id >= TRX_RSEG_N_SLOTS)) {
1507  fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
1508  (ulong) undo->id);
1509 
1510  mem_analyze_corruption(undo);
1511  ut_error;
1512  }
1513 
1514  undo->state = TRX_UNDO_ACTIVE;
1515  undo->del_marks = FALSE;
1516  undo->trx_id = trx_id;
1517  undo->xid = *xid;
1518 
1519  undo->dict_operation = FALSE;
1520 
1521  undo->hdr_offset = offset;
1522  undo->empty = TRUE;
1523 }
1524 
1525 /********************************************************************/
1527 UNIV_INTERN
1528 void
1530 /*==============*/
1531  trx_undo_t* undo)
1532 {
1533  if (undo->id >= TRX_RSEG_N_SLOTS) {
1534  fprintf(stderr,
1535  "InnoDB: Error: undo->id is %lu\n", (ulong) undo->id);
1536  ut_error;
1537  }
1538 
1539  mem_free(undo);
1540 }
1541 
1542 /**********************************************************************/
1547 static
1548 ulint
1549 trx_undo_create(
1550 /*============*/
1551  trx_t* trx,
1552  trx_rseg_t* rseg,
1553  ulint type,
1555  trx_id_t trx_id,
1557  const XID* xid,
1558  trx_undo_t** undo,
1560  mtr_t* mtr)
1561 {
1562  trx_rsegf_t* rseg_header;
1563  ulint page_no;
1564  ulint offset;
1565  ulint id;
1566  page_t* undo_page;
1567  ulint err;
1568 
1569  ut_ad(mutex_own(&(rseg->mutex)));
1570 
1571  if (rseg->curr_size == rseg->max_size) {
1572 
1573  return(DB_OUT_OF_FILE_SPACE);
1574  }
1575 
1576  rseg->curr_size++;
1577 
1578  rseg_header = trx_rsegf_get(rseg->space, rseg->zip_size, rseg->page_no,
1579  mtr);
1580 
1581  err = trx_undo_seg_create(rseg, rseg_header, type, &id,
1582  &undo_page, mtr);
1583 
1584  if (err != DB_SUCCESS) {
1585  /* Did not succeed */
1586 
1587  rseg->curr_size--;
1588 
1589  return(err);
1590  }
1591 
1592  page_no = page_get_page_no(undo_page);
1593 
1594  offset = trx_undo_header_create(undo_page, trx_id, mtr);
1595 
1596  if (trx->support_xa) {
1597  trx_undo_header_add_space_for_xid(undo_page,
1598  undo_page + offset, mtr);
1599  }
1600 
1601  *undo = trx_undo_mem_create(rseg, id, type, trx_id, xid,
1602  page_no, offset);
1603  if (*undo == NULL) {
1604 
1605  err = DB_OUT_OF_MEMORY;
1606  }
1607 
1608  return(err);
1609 }
1610 
1611 /*================ UNDO LOG ASSIGNMENT AND CLEANUP =====================*/
1612 
1613 /********************************************************************/
1616 static
1617 trx_undo_t*
1618 trx_undo_reuse_cached(
1619 /*==================*/
1620  trx_t* trx,
1621  trx_rseg_t* rseg,
1622  ulint type,
1624  trx_id_t trx_id,
1626  const XID* xid,
1627  mtr_t* mtr)
1628 {
1629  trx_undo_t* undo;
1630  page_t* undo_page;
1631  ulint offset;
1632 
1633  ut_ad(mutex_own(&(rseg->mutex)));
1634 
1635  if (type == TRX_UNDO_INSERT) {
1636 
1637  undo = UT_LIST_GET_FIRST(rseg->insert_undo_cached);
1638  if (undo == NULL) {
1639 
1640  return(NULL);
1641  }
1642 
1643  UT_LIST_REMOVE(undo_list, rseg->insert_undo_cached, undo);
1644  } else {
1645  ut_ad(type == TRX_UNDO_UPDATE);
1646 
1647  undo = UT_LIST_GET_FIRST(rseg->update_undo_cached);
1648  if (undo == NULL) {
1649 
1650  return(NULL);
1651  }
1652 
1653  UT_LIST_REMOVE(undo_list, rseg->update_undo_cached, undo);
1654  }
1655 
1656  ut_ad(undo->size == 1);
1657 
1658  if (undo->id >= TRX_RSEG_N_SLOTS) {
1659  fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
1660  (ulong) undo->id);
1661  mem_analyze_corruption(undo);
1662  ut_error;
1663  }
1664 
1665  undo_page = trx_undo_page_get(undo->space, undo->zip_size,
1666  undo->hdr_page_no, mtr);
1667 
1668  if (type == TRX_UNDO_INSERT) {
1669  offset = trx_undo_insert_header_reuse(undo_page, trx_id, mtr);
1670 
1671  if (trx->support_xa) {
1672  trx_undo_header_add_space_for_xid(
1673  undo_page, undo_page + offset, mtr);
1674  }
1675  } else {
1676  ut_a(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
1678  == TRX_UNDO_UPDATE);
1679 
1680  offset = trx_undo_header_create(undo_page, trx_id, mtr);
1681 
1682  if (trx->support_xa) {
1683  trx_undo_header_add_space_for_xid(
1684  undo_page, undo_page + offset, mtr);
1685  }
1686  }
1687 
1688  trx_undo_mem_init_for_reuse(undo, trx_id, xid, offset);
1689 
1690  return(undo);
1691 }
1692 
1693 /**********************************************************************/
1696 static
1697 void
1698 trx_undo_mark_as_dict_operation(
1699 /*============================*/
1700  trx_t* trx,
1701  trx_undo_t* undo,
1702  mtr_t* mtr)
1703 {
1704  page_t* hdr_page;
1705 
1706  hdr_page = trx_undo_page_get(undo->space, undo->zip_size,
1707  undo->hdr_page_no, mtr);
1708 
1709  switch (trx_get_dict_operation(trx)) {
1710  case TRX_DICT_OP_NONE:
1711  ut_error;
1712  case TRX_DICT_OP_INDEX:
1713  /* Do not discard the table on recovery. */
1714  undo->table_id = 0;
1715  break;
1716  case TRX_DICT_OP_TABLE:
1717  undo->table_id = trx->table_id;
1718  break;
1719  }
1720 
1721  mlog_write_ulint(hdr_page + undo->hdr_offset
1723  TRUE, MLOG_1BYTE, mtr);
1724 
1725  mlog_write_ull(hdr_page + undo->hdr_offset + TRX_UNDO_TABLE_ID,
1726  undo->table_id, mtr);
1727 
1728  undo->dict_operation = TRUE;
1729 }
1730 
1731 /**********************************************************************/
1737 UNIV_INTERN
1738 ulint
1740 /*=================*/
1741  trx_t* trx,
1742  ulint type)
1743 {
1744  trx_rseg_t* rseg;
1745  trx_undo_t* undo;
1746  mtr_t mtr;
1747  ulint err = DB_SUCCESS;
1748 
1749  ut_ad(trx);
1750  ut_ad(trx->rseg);
1751 
1752  rseg = trx->rseg;
1753 
1754  ut_ad(mutex_own(&(trx->undo_mutex)));
1755 
1756  mtr_start(&mtr);
1757 
1758  ut_ad(!mutex_own(&kernel_mutex));
1759 
1760  mutex_enter(&(rseg->mutex));
1761 
1762  undo = trx_undo_reuse_cached(trx, rseg, type, trx->id, &trx->xid,
1763  &mtr);
1764  if (undo == NULL) {
1765  err = trx_undo_create(trx, rseg, type, trx->id, &trx->xid,
1766  &undo, &mtr);
1767  if (err != DB_SUCCESS) {
1768 
1769  goto func_exit;
1770  }
1771  }
1772 
1773  if (type == TRX_UNDO_INSERT) {
1774  UT_LIST_ADD_FIRST(undo_list, rseg->insert_undo_list, undo);
1775  ut_ad(trx->insert_undo == NULL);
1776  trx->insert_undo = undo;
1777  } else {
1778  UT_LIST_ADD_FIRST(undo_list, rseg->update_undo_list, undo);
1779  ut_ad(trx->update_undo == NULL);
1780  trx->update_undo = undo;
1781  }
1782 
1784  trx_undo_mark_as_dict_operation(trx, undo, &mtr);
1785  }
1786 
1787 func_exit:
1788  mutex_exit(&(rseg->mutex));
1789  mtr_commit(&mtr);
1790 
1791  return err;
1792 }
1793 
1794 /******************************************************************/
1797 UNIV_INTERN
1798 page_t*
1800 /*=========================*/
1801  trx_undo_t* undo,
1802  mtr_t* mtr)
1803 {
1804  trx_usegf_t* seg_hdr;
1805  trx_upagef_t* page_hdr;
1806  page_t* undo_page;
1807  ulint state;
1808 
1809  ut_ad(undo);
1810  ut_ad(mtr);
1811 
1812  if (undo->id >= TRX_RSEG_N_SLOTS) {
1813  fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
1814  (ulong) undo->id);
1815  mem_analyze_corruption(undo);
1816  ut_error;
1817  }
1818 
1819  undo_page = trx_undo_page_get(undo->space, undo->zip_size,
1820  undo->hdr_page_no, mtr);
1821 
1822  seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
1823  page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
1824 
1825  if (undo->size == 1
1826  && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
1828 
1829  state = TRX_UNDO_CACHED;
1830 
1831  } else if (undo->type == TRX_UNDO_INSERT) {
1832 
1833  state = TRX_UNDO_TO_FREE;
1834  } else {
1835  state = TRX_UNDO_TO_PURGE;
1836  }
1837 
1838  undo->state = state;
1839 
1840  mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, state, MLOG_2BYTES, mtr);
1841 
1842  return(undo_page);
1843 }
1844 
1845 /******************************************************************/
1848 UNIV_INTERN
1849 page_t*
1851 /*==========================*/
1852  trx_t* trx,
1853  trx_undo_t* undo,
1854  mtr_t* mtr)
1855 {
1856  trx_usegf_t* seg_hdr;
1857  trx_ulogf_t* undo_header;
1858  page_t* undo_page;
1859  ulint offset;
1860 
1861  ut_ad(trx && undo && mtr);
1862 
1863  if (undo->id >= TRX_RSEG_N_SLOTS) {
1864  fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
1865  (ulong) undo->id);
1866  mem_analyze_corruption(undo);
1867  ut_error;
1868  }
1869 
1870  undo_page = trx_undo_page_get(undo->space, undo->zip_size,
1871  undo->hdr_page_no, mtr);
1872 
1873  seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
1874 
1875  /*------------------------------*/
1876  undo->state = TRX_UNDO_PREPARED;
1877  undo->xid = trx->xid;
1878  /*------------------------------*/
1879 
1880  mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, undo->state,
1881  MLOG_2BYTES, mtr);
1882 
1883  offset = mach_read_from_2(seg_hdr + TRX_UNDO_LAST_LOG);
1884  undo_header = undo_page + offset;
1885 
1886  mlog_write_ulint(undo_header + TRX_UNDO_XID_EXISTS,
1887  TRUE, MLOG_1BYTE, mtr);
1888 
1889  trx_undo_write_xid(undo_header, &undo->xid, mtr);
1890 
1891  return(undo_page);
1892 }
1893 
1894 /**********************************************************************/
1898 UNIV_INTERN
1899 void
1901 /*====================*/
1902  trx_t* trx,
1903  page_t* undo_page,
1905  mtr_t* mtr)
1906 {
1907  trx_rseg_t* rseg;
1908  trx_undo_t* undo;
1909 
1910  undo = trx->update_undo;
1911  rseg = trx->rseg;
1912 
1913  ut_ad(mutex_own(&(rseg->mutex)));
1914 
1915  trx_purge_add_update_undo_to_history(trx, undo_page, mtr);
1916 
1917  UT_LIST_REMOVE(undo_list, rseg->update_undo_list, undo);
1918 
1919  trx->update_undo = NULL;
1920 
1921  if (undo->state == TRX_UNDO_CACHED) {
1922 
1923  UT_LIST_ADD_FIRST(undo_list, rseg->update_undo_cached, undo);
1924  } else {
1925  ut_ad(undo->state == TRX_UNDO_TO_PURGE
1926  || undo->state == TRX_UNDO_TO_FREE);
1927 
1928  trx_undo_mem_free(undo);
1929  }
1930 }
1931 
1932 /******************************************************************/
1936 UNIV_INTERN
1937 void
1939 /*====================*/
1940  trx_t* trx)
1941 {
1942  trx_undo_t* undo;
1943  trx_rseg_t* rseg;
1944 
1945  undo = trx->insert_undo;
1946  ut_ad(undo);
1947 
1948  rseg = trx->rseg;
1949 
1950  mutex_enter(&(rseg->mutex));
1951 
1952  UT_LIST_REMOVE(undo_list, rseg->insert_undo_list, undo);
1953  trx->insert_undo = NULL;
1954 
1955  if (undo->state == TRX_UNDO_CACHED) {
1956 
1957  UT_LIST_ADD_FIRST(undo_list, rseg->insert_undo_cached, undo);
1958  } else {
1959  ut_ad(undo->state == TRX_UNDO_TO_FREE);
1960 
1961  /* Delete first the undo log segment in the file */
1962 
1963  mutex_exit(&(rseg->mutex));
1964 
1965  trx_undo_seg_free(undo);
1966 
1967  mutex_enter(&(rseg->mutex));
1968 
1969  ut_ad(rseg->curr_size > undo->size);
1970 
1971  rseg->curr_size -= undo->size;
1972 
1973  trx_undo_mem_free(undo);
1974  }
1975 
1976  mutex_exit(&(rseg->mutex));
1977 }
1978 #endif /* !UNIV_HOTBACKUP */
#define TRX_UNDO_LAST_LOG
Definition: trx0undo.h:475
#define TRX_UNDO_PAGE_HDR
Definition: trx0undo.h:422
undo_no_t top_undo_no
Definition: trx0undo.h:411
#define TRX_UNDO_TABLE_ID
Definition: trx0undo.h:539
buf_block_t * guess_block
Definition: trx0undo.h:412
byte trx_undo_rec_t
Definition: trx0types.h:112
XID xid
Definition: trx0trx.h:549
UNIV_INLINE ulint page_get_space_id(const page_t *page)
byte trx_upagef_t
Definition: trx0types.h:109
UNIV_INLINE fil_addr_t flst_get_last(const flst_base_node_t *base, mtr_t *mtr)
byte trx_usegf_t
Definition: trx0types.h:105
UNIV_INLINE ulint trx_rsegf_undo_find_free(trx_rsegf_t *rsegf, mtr_t *mtr)
#define MLOG_UNDO_HDR_CREATE
Definition: mtr0mtr.h:120
#define TRX_UNDO_TRX_ID
Definition: trx0undo.h:497
#define TRX_UNDO_DICT_TRANS
Definition: trx0undo.h:526
trx_id_t id
Definition: trx0trx.h:548
UNIV_INLINE fil_addr_t flst_get_prev_addr(const flst_node_t *node, mtr_t *mtr)
UNIV_INLINE page_t * page_align(const void *ptr) __attribute__((const ))
UNIV_INLINE void mlog_catenate_ull_compressed(mtr_t *mtr, ib_uint64_t val)
UNIV_INLINE ulint page_get_page_no(const page_t *page)
trx_undo_t * insert_undo
Definition: trx0trx.h:696
ulint zip_size
Definition: trx0undo.h:391
UNIV_INTERN ulint fseg_alloc_free_page_general(fseg_header_t *seg_header, ulint hint, byte direction, ibool has_done_reservation, mtr_t *mtr)
Definition: fsp0fsp.cc:2802
UNIV_INLINE fil_addr_t flst_get_next_addr(const flst_node_t *node, mtr_t *mtr)
table_id_t table_id
Definition: trx0trx.h:556
byte trx_ulogf_t
Definition: trx0types.h:107
long gtrid_length
Definition: trx0xa.h:44
mutex_t undo_mutex
Definition: trx0trx.h:675
UNIV_INTERN void flst_add_last(flst_base_node_t *base, flst_node_t *node, mtr_t *mtr)
Definition: fut0lst.cc:75
UNIV_INTERN ulint trx_undo_add_page(trx_t *trx, trx_undo_t *undo, mtr_t *mtr)
Definition: trx0undo.cc:881
#define mem_free(PTR)
Definition: mem0mem.h:249
UNIV_INLINE ulint trx_rsegf_get_nth_undo(trx_rsegf_t *rsegf, ulint n, mtr_t *mtr)
#define MLOG_1BYTE
Definition: mtr0mtr.h:73
#define TRX_UNDO_PAGE_REUSE_LIMIT
Definition: trx0undo.h:456
UNIV_INTERN void mlog_write_string(byte *ptr, const byte *str, ulint len, mtr_t *mtr)
Definition: mtr0log.cc:330
UNIV_INTERN void trx_undo_update_cleanup(trx_t *trx, page_t *undo_page, mtr_t *mtr)
Definition: trx0undo.cc:1900
UNIV_INTERN void trx_undo_mem_free(trx_undo_t *undo)
Definition: trx0undo.cc:1529
long bqual_length
Definition: trx0xa.h:45
UNIV_INLINE void mach_write_to_8(byte *b, ib_uint64_t n)
ulint hdr_offset
Definition: trx0undo.h:395
UNIV_INTERN void mlog_write_ulint(byte *ptr, ulint val, byte type, mtr_t *mtr)
Definition: mtr0log.cc:247
#define TRX_UNDO_XA_XID
Definition: trx0undo.h:572
UNIV_INLINE void flst_init(flst_base_node_t *base, mtr_t *mtr)
UNIV_INLINE byte * mach_ull_parse_compressed(byte *ptr, byte *end_ptr, ib_uint64_t *val)
UNIV_INTERN ulint fil_space_get_zip_size(ulint id)
Definition: fil0fil.cc:1535
#define TRX_UNDO_NEXT_LOG
Definition: trx0undo.h:542
UNIV_INTERN byte * trx_undo_parse_discard_latest(byte *ptr, byte *end_ptr, page_t *page, mtr_t *mtr)
Definition: trx0undo.cc:817
UNIV_INTERN void trx_undo_truncate_start(trx_rseg_t *rseg, ulint space, ulint hdr_page_no, ulint hdr_offset, undo_no_t limit)
Definition: trx0undo.cc:1135
#define ut_d(EXPR)
Definition: ut0dbg.h:129
UNIV_INTERN void flst_remove(flst_base_node_t *base, flst_node_t *node2, mtr_t *mtr)
Definition: fut0lst.cc:270
mutex_t mutex
Definition: trx0rseg.h:146
char data[XIDDATASIZE]
Definition: trx0xa.h:46
ibool del_marks
Definition: trx0undo.h:372
#define MLOG_UNDO_HDR_DISCARD
Definition: mtr0mtr.h:114
#define TRX_UNDO_LOG_START
Definition: trx0undo.h:510
UNIV_INTERN page_t * trx_undo_set_state_at_finish(trx_undo_t *undo, mtr_t *mtr)
Definition: trx0undo.cc:1799
#define TRX_UNDO_XA_BQUAL_LEN
Definition: trx0undo.h:570
UNIV_INTERN void fseg_free_page(fseg_header_t *seg_header, ulint space, ulint page, mtr_t *mtr)
Definition: fsp0fsp.cc:3403
#define TRX_UNDO_FSEG_HEADER
Definition: trx0undo.h:480
UNIV_INLINE trx_rsegf_t * trx_rsegf_get_new(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
trx_rseg_t * rseg
Definition: trx0undo.h:387
UNIV_INTERN ibool fsp_reserve_free_extents(ulint *n_reserved, ulint space, ulint n_ext, ulint alloc_type, mtr_t *mtr)
Definition: fsp0fsp.cc:2955
#define TRX_UNDO_SEG_HDR
Definition: trx0undo.h:470
trx_id_t trx_id
Definition: trx0undo.h:380
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 page_t * trx_undo_page_get(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
#define TRX_UNDO_SEG_HDR_SIZE
Definition: trx0undo.h:489
UNIV_INTERN void mlog_write_ull(byte *ptr, ib_uint64_t val, mtr_t *mtr)
Definition: mtr0log.cc:293
UNIV_INTERN void fil_page_set_type(byte *page, ulint type)
Definition: fil0fil.cc:4899
ulint top_offset
Definition: trx0undo.h:408
UNIV_INTERN byte * mach_parse_compressed(byte *ptr, byte *end_ptr, ulint *val)
Definition: mach0data.cc:38
trx_rseg_t * rseg
Definition: trx0trx.h:693
UNIV_INTERN void trx_undo_insert_cleanup(trx_t *trx)
Definition: trx0undo.cc:1938
#define MLOG_UNDO_INIT
Definition: mtr0mtr.h:111
#define MLOG_2BYTES
Definition: mtr0mtr.h:74
ibool dict_operation
Definition: trx0undo.h:384
UNIV_INLINE trx_rsegf_t * trx_rsegf_get(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
Definition: trx0xa.h:41
#define ut_a(EXPR)
Definition: ut0dbg.h:105
UNIV_INTERN page_t * trx_undo_set_state_at_prepare(trx_t *trx, trx_undo_t *undo, mtr_t *mtr)
Definition: trx0undo.cc:1850
UNIV_INLINE trx_undo_rec_t * trx_undo_page_get_prev_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset)
#define TRX_UNDO_LOG_OLD_HDR_SIZE
Definition: trx0undo.h:553
UNIV_INLINE trx_undo_rec_t * trx_undo_page_get_last_rec(page_t *undo_page, ulint page_no, ulint offset)
long formatID
Definition: trx0xa.h:42
UNIV_INLINE void mach_write_to_1(byte *b, ulint n)
UNIV_INTERN trx_undo_rec_t * trx_undo_get_next_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset, mtr_t *mtr)
Definition: trx0undo.cc:273
#define TRX_UNDO_XA_TRID_LEN
Definition: trx0undo.h:568
#define TRX_UNDO_STATE
Definition: trx0undo.h:474
#define UT_LIST_ADD_LAST(NAME, BASE, N)
Definition: ut0lst.h:119
#define UT_LIST_GET_FIRST(BASE)
Definition: ut0lst.h:224
UNIV_INLINE trx_undo_rec_t * trx_undo_page_get_first_rec(page_t *undo_page, ulint page_no, ulint offset)
UNIV_INLINE trx_undo_rec_t * trx_undo_page_get_next_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset)
UNIV_INTERN void mlog_write_initial_log_record(const byte *ptr, byte type, mtr_t *mtr)
Definition: mtr0log.cc:68
#define TRX_UNDO_XID_EXISTS
Definition: trx0undo.h:521
#define MLOG_4BYTES
Definition: mtr0mtr.h:75
UNIV_INLINE undo_no_t trx_undo_rec_get_undo_no(const trx_undo_rec_t *undo_rec)
#define ut_ad(EXPR)
Definition: ut0dbg.h:127
UNIV_INTERN void fil_space_release_free_extents(ulint id, ulint n_reserved)
Definition: fil0fil.cc:4116
ib_id_t trx_id_t
Definition: trx0types.h:85
#define TRX_UNDO_PAGE_HDR_SIZE
Definition: trx0undo.h:447
#define UT_LIST_INIT(BASE)
Definition: ut0lst.h:84
#define TRX_UNDO_PAGE_NODE
Definition: trx0undo.h:443
UNIV_INTERN trx_undo_rec_t * trx_undo_get_first_rec(ulint space, ulint zip_size, ulint page_no, ulint offset, ulint mode, mtr_t *mtr)
Definition: trx0undo.cc:304
#define ut_error
Definition: ut0dbg.h:115
#define MLOG_UNDO_HDR_REUSE
Definition: mtr0mtr.h:117
#define FIL_NULL
Definition: fil0fil.h:48
table_id_t table_id
Definition: trx0undo.h:385
UNIV_INTERN void trx_purge_add_update_undo_to_history(trx_t *trx, page_t *undo_page, mtr_t *mtr)
Definition: trx0purge.cc:313
ulint hdr_page_no
Definition: trx0undo.h:393
UNIV_INLINE enum trx_dict_op trx_get_dict_operation(const trx_t *trx) __attribute__((pure))
ulint top_page_no
Definition: trx0undo.h:404
#define UT_LIST_ADD_FIRST(NAME, BASE, N)
Definition: ut0lst.h:97
UNIV_INTERN ulint trx_undo_assign_undo(trx_t *trx, ulint type)
Definition: trx0undo.cc:1739
UNIV_INLINE ulint mach_read_from_4(const byte *b) __attribute__((nonnull
UNIV_INTERN void ut_print_timestamp(FILE *file)
Definition: ut0ut.cc:247
#define FIL_PAGE_UNDO_LOG
Definition: fil0fil.h:174
UNIV_INLINE void mach_write_to_2(byte *b, ulint n)
#define TRX_UNDO_PAGE_TYPE
Definition: trx0undo.h:426
ulint last_page_no
Definition: trx0undo.h:397
byte page_t
Definition: page0types.h:37
unsigned support_xa
Definition: trx0trx.h:496
#define TRX_UNDO_PREV_LOG
Definition: trx0undo.h:545
UNIV_INTERN void mem_analyze_corruption(void *ptr)
Definition: mem0dbg.cc:822
ulint page
Definition: fil0fil.h:67
UNIV_INLINE void mtr_start(mtr_t *mtr) __attribute__((nonnull))
UNIV_INTERN byte * trx_undo_parse_page_init(byte *ptr, byte *end_ptr, page_t *page, mtr_t *mtr)
Definition: trx0undo.cc:360
#define TRX_UNDO_DEL_MARKS
Definition: trx0undo.h:503
#define TRX_UNDO_PAGE_FREE
Definition: trx0undo.h:438
UNIV_INLINE ulint mach_read_from_2(const byte *b) __attribute__((nonnull
#define TRX_UNDO_PAGE_START
Definition: trx0undo.h:429
trx_undo_t * update_undo
Definition: trx0trx.h:698
UNIV_INTERN void trx_undo_truncate_end(trx_t *trx, trx_undo_t *undo, undo_no_t limit)
Definition: trx0undo.cc:1064
#define TRX_UNDO_XA_FORMAT
Definition: trx0undo.h:566
UNIV_INTERN ulint trx_undo_lists_init(trx_rseg_t *rseg)
Definition: trx0undo.cc:1382
UNIV_INTERN buf_block_t * fseg_create_general(ulint space, ulint page, ulint byte_offset, ibool has_done_reservation, mtr_t *mtr)
Definition: fsp0fsp.cc:2218
#define TRX_UNDO_PAGE_LIST
Definition: trx0undo.h:483
UNIV_INLINE ib_uint64_t mach_read_from_8(const byte *b) __attribute__((nonnull
#define TRX_UNDO_LOG_XA_HDR_SIZE
Definition: trx0undo.h:574
UNIV_INTERN byte * trx_undo_parse_page_header(ulint type, byte *ptr, byte *end_ptr, page_t *page, mtr_t *mtr)
Definition: trx0undo.cc:701
UNIV_INLINE ulint flst_get_len(const flst_base_node_t *base, mtr_t *mtr)
ib_id_t undo_no_t
Definition: trx0types.h:89
byte trx_rsegf_t
Definition: trx0types.h:103
UNIV_INLINE page_t * trx_undo_page_get_s_latched(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
UNIV_INTERN ibool fseg_free_step(fseg_header_t *header, mtr_t *mtr)
Definition: fsp0fsp.cc:3512
UNIV_INLINE void trx_rsegf_set_nth_undo(trx_rsegf_t *rsegf, ulint n, ulint page_no, mtr_t *mtr)
UNIV_INLINE void mlog_catenate_ulint_compressed(mtr_t *mtr, ulint val)
UNIV_INTERN trx_undo_rec_t * trx_undo_get_prev_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset, mtr_t *mtr)
Definition: trx0undo.cc:193