#include "trx0rec.h"#include "fsp0fsp.h"#include "mach0data.h"#include "trx0rseg.h"#include "trx0trx.h"#include "trx0undo.h"#include "dict0dict.h"#include "ut0mem.h"#include "row0upd.h"#include "que0que.h"#include "trx0purge.h"#include "row0row.h"Include dependency graph for trx0rec.c:

Go to the source code of this file.
Definition at line 943 of file trx0rec.c.
References FIL_PAGE_DATA_END, mach_read_from_2(), memset, MLOG_UNDO_ERASE_END, mlog_write_initial_log_record(), TRX_UNDO_PAGE_FREE, TRX_UNDO_PAGE_HDR, and UNIV_PAGE_SIZE.
Referenced by trx_undo_parse_erase_page_end(), and trx_undo_report_row_operation().
00945 : undo page whose end to erase */ 00946 mtr_t* mtr) /* in: mtr */ 00947 { 00948 ulint first_free; 00949 00950 first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR 00951 + TRX_UNDO_PAGE_FREE); 00952 memset(undo_page + first_free, 0xff, 00953 (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END) - first_free); 00954 00955 mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr); 00956 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint trx_undo_get_undo_rec | ( | dulint | roll_ptr, | |
| dulint | trx_id, | |||
| trx_undo_rec_t ** | undo_rec, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 1206 of file trx0rec.c.
References DB_MISSING_HISTORY, DB_SUCCESS, trx_purge_struct::latch, purge_sys, RW_LOCK_SHARED, trx_purge_update_undo_must_exist(), trx_undo_get_undo_rec_low(), and ut_ad.
Referenced by trx_undo_prev_version_build().
01208 : DB_SUCCESS, or 01209 DB_MISSING_HISTORY if the undo log 01210 has been truncated and we cannot 01211 fetch the old version; NOTE: the 01212 caller must have latches on the 01213 clustered index page and purge_view */ 01214 dulint roll_ptr, /* in: roll pointer to record */ 01215 dulint trx_id, /* in: id of the trx that generated 01216 the roll pointer: it points to an 01217 undo log of this transaction */ 01218 trx_undo_rec_t** undo_rec, /* out, own: copy of the record */ 01219 mem_heap_t* heap) /* in: memory heap where copied */ 01220 { 01221 #ifdef UNIV_SYNC_DEBUG 01222 ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); 01223 #endif /* UNIV_SYNC_DEBUG */ 01224 01225 if (!trx_purge_update_undo_must_exist(trx_id)) { 01226 01227 /* It may be that the necessary undo log has already been 01228 deleted */ 01229 01230 return(DB_MISSING_HISTORY); 01231 } 01232 01233 *undo_rec = trx_undo_get_undo_rec_low(roll_ptr, heap); 01234 01235 return(DB_SUCCESS); 01236 }
Here is the call graph for this function:

Here is the caller graph for this function:

| trx_undo_rec_t* trx_undo_get_undo_rec_low | ( | dulint | roll_ptr, | |
| mem_heap_t * | heap | |||
| ) |
Definition at line 1172 of file trx0rec.c.
References mtr_commit(), mtr_start(), offset, page_t, trx_rseg_struct::space, trx_rseg_get_on_id(), trx_undo_decode_roll_ptr(), trx_undo_page_get_s_latched(), and trx_undo_rec_copy().
Referenced by row_undo(), row_undo_mod_undo_also_prev_vers(), row_vers_build_for_consistent_read(), and trx_undo_get_undo_rec().
01174 : copy of the record */ 01175 dulint roll_ptr, /* in: roll pointer to record */ 01176 mem_heap_t* heap) /* in: memory heap where copied */ 01177 { 01178 trx_undo_rec_t* undo_rec; 01179 ulint rseg_id; 01180 ulint page_no; 01181 ulint offset; 01182 page_t* undo_page; 01183 trx_rseg_t* rseg; 01184 ibool is_insert; 01185 mtr_t mtr; 01186 01187 trx_undo_decode_roll_ptr(roll_ptr, &is_insert, &rseg_id, &page_no, 01188 &offset); 01189 rseg = trx_rseg_get_on_id(rseg_id); 01190 01191 mtr_start(&mtr); 01192 01193 undo_page = trx_undo_page_get_s_latched(rseg->space, page_no, &mtr); 01194 01195 undo_rec = trx_undo_rec_copy(undo_page + offset, heap); 01196 01197 mtr_commit(&mtr); 01198 01199 return(undo_rec); 01200 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 120 of file trx0rec.c.
References FIL_PAGE_DATA_END, and UNIV_PAGE_SIZE.
Referenced by trx_undo_page_report_insert(), and trx_undo_page_report_modify().
00122 : bytes left */ 00123 page_t* page, /* in: undo log page */ 00124 byte* ptr) /* in: pointer to page */ 00125 { 00126 /* The '- 10' is a safety margin, in case we have some small 00127 calculation error below */ 00128 00129 return(UNIV_PAGE_SIZE - (ptr - page) - 10 - FIL_PAGE_DATA_END); 00130 }
Here is the caller graph for this function:

| static ulint trx_undo_page_report_insert | ( | page_t * | undo_page, | |
| trx_t * | trx, | |||
| dict_index_t * | index, | |||
| dtuple_t * | clust_entry, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 136 of file trx0rec.c.
References dfield_get_data(), dfield_get_len(), dict_index_get_n_unique(), dtuple_get_nth_field(), index(), mach_dulint_write_much_compressed(), mach_read_from_2(), mach_write_compressed(), mach_write_to_1(), mach_write_to_2(), TRX_UNDO_INSERT, TRX_UNDO_INSERT_REC, trx_undo_left(), TRX_UNDO_PAGE_FREE, TRX_UNDO_PAGE_HDR, TRX_UNDO_PAGE_TYPE, trx_undof_page_add_undo_rec_log(), trx_struct::undo_no, UNIV_PAGE_SIZE, ut_ad, and ut_memcpy().
Referenced by trx_undo_report_row_operation().
00138 : offset of the inserted entry 00139 on the page if succeed, 0 if fail */ 00140 page_t* undo_page, /* in: undo log page */ 00141 trx_t* trx, /* in: transaction */ 00142 dict_index_t* index, /* in: clustered index */ 00143 dtuple_t* clust_entry, /* in: index entry which will be 00144 inserted to the clustered index */ 00145 mtr_t* mtr) /* in: mtr */ 00146 { 00147 ulint first_free; 00148 byte* ptr; 00149 ulint len; 00150 dfield_t* field; 00151 ulint flen; 00152 ulint i; 00153 00154 ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR 00155 + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_INSERT); 00156 00157 first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR 00158 + TRX_UNDO_PAGE_FREE); 00159 ptr = undo_page + first_free; 00160 00161 ut_ad(first_free <= UNIV_PAGE_SIZE); 00162 00163 if (trx_undo_left(undo_page, ptr) < 30) { 00164 00165 /* NOTE: the value 30 must be big enough such that the general 00166 fields written below fit on the undo log page */ 00167 00168 return(0); 00169 } 00170 00171 /* Reserve 2 bytes for the pointer to the next undo log record */ 00172 ptr += 2; 00173 00174 /* Store first some general parameters to the undo log */ 00175 mach_write_to_1(ptr, TRX_UNDO_INSERT_REC); 00176 ptr++; 00177 00178 len = mach_dulint_write_much_compressed(ptr, trx->undo_no); 00179 ptr += len; 00180 00181 len = mach_dulint_write_much_compressed(ptr, (index->table)->id); 00182 ptr += len; 00183 /*----------------------------------------*/ 00184 /* Store then the fields required to uniquely determine the record 00185 to be inserted in the clustered index */ 00186 00187 for (i = 0; i < dict_index_get_n_unique(index); i++) { 00188 00189 field = dtuple_get_nth_field(clust_entry, i); 00190 00191 flen = dfield_get_len(field); 00192 00193 if (trx_undo_left(undo_page, ptr) < 5) { 00194 00195 return(0); 00196 } 00197 00198 len = mach_write_compressed(ptr, flen); 00199 ptr += len; 00200 00201 if (flen != UNIV_SQL_NULL) { 00202 if (trx_undo_left(undo_page, ptr) < flen) { 00203 00204 return(0); 00205 } 00206 00207 ut_memcpy(ptr, dfield_get_data(field), flen); 00208 ptr += flen; 00209 } 00210 } 00211 00212 if (trx_undo_left(undo_page, ptr) < 2) { 00213 00214 return(0); 00215 } 00216 00217 /*----------------------------------------*/ 00218 /* Write pointers to the previous and the next undo log records */ 00219 00220 if (trx_undo_left(undo_page, ptr) < 2) { 00221 00222 return(0); 00223 } 00224 00225 mach_write_to_2(ptr, first_free); 00226 ptr += 2; 00227 00228 mach_write_to_2(undo_page + first_free, ptr - undo_page); 00229 00230 mach_write_to_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE, 00231 ptr - undo_page); 00232 00233 /* Write the log entry to the REDO log of this change in the UNDO 00234 log */ 00235 trx_undof_page_add_undo_rec_log(undo_page, first_free, 00236 ptr - undo_page, mtr); 00237 return(first_free); 00238 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint trx_undo_page_report_modify | ( | page_t * | undo_page, | |
| trx_t * | trx, | |||
| dict_index_t * | index, | |||
| rec_t * | rec, | |||
| const ulint * | offsets, | |||
| upd_t * | update, | |||
| ulint | cmpl_info, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 395 of file trx0rec.c.
References DATA_ROLL_PTR, DATA_ROLL_PTR_LEN, DATA_TRX_ID, DATA_TRX_ID_LEN, trx_undo_struct::del_marks, DICT_CLUSTERED, dict_index_get_n_unique(), dict_index_get_nth_col_pos(), dict_index_get_sys_col_pos(), dict_table_get_n_cols(), dict_table_get_nth_col(), dict_table_is_comp(), upd_field_struct::field_no, dict_table_struct::id, index(), mach_dulint_write_compressed(), mach_dulint_write_much_compressed(), mach_read_from_2(), mach_write_compressed(), mach_write_to_1(), mach_write_to_2(), dict_col_struct::ord_part, pos(), rec_get_deleted_flag(), rec_get_info_bits(), rec_get_nth_field(), rec_offs_nth_extern(), rec_offs_validate(), TRUE, trx_read_roll_ptr(), trx_read_trx_id(), TRX_UNDO_CMPL_INFO_MULT, TRX_UNDO_DEL_MARK_REC, trx_undo_left(), TRX_UNDO_PAGE_FREE, TRX_UNDO_PAGE_HDR, TRX_UNDO_PAGE_TYPE, TRX_UNDO_UPD_DEL_REC, TRX_UNDO_UPD_EXIST_REC, TRX_UNDO_UPD_EXTERN, TRX_UNDO_UPDATE, trx_undof_page_add_undo_rec_log(), trx_struct::undo_no, UNIV_PAGE_SIZE, upd_get_n_fields(), upd_get_nth_field(), UPD_NODE_NO_ORD_CHANGE, update, trx_struct::update_undo, ut_a, ut_ad, and ut_memcpy().
Referenced by trx_undo_report_row_operation().
00397 : byte offset of the inserted 00398 undo log entry on the page if succeed, 00399 0 if fail */ 00400 page_t* undo_page, /* in: undo log page */ 00401 trx_t* trx, /* in: transaction */ 00402 dict_index_t* index, /* in: clustered index where update or 00403 delete marking is done */ 00404 rec_t* rec, /* in: clustered index record which 00405 has NOT yet been modified */ 00406 const ulint* offsets, /* in: rec_get_offsets(rec, index) */ 00407 upd_t* update, /* in: update vector which tells the 00408 columns to be updated; in the case of 00409 a delete, this should be set to NULL */ 00410 ulint cmpl_info, /* in: compiler info on secondary 00411 index updates */ 00412 mtr_t* mtr) /* in: mtr */ 00413 { 00414 dict_table_t* table; 00415 upd_field_t* upd_field; 00416 dict_col_t* col; 00417 ulint first_free; 00418 byte* ptr; 00419 ulint len; 00420 byte* field; 00421 ulint flen; 00422 ulint pos; 00423 dulint roll_ptr; 00424 dulint trx_id; 00425 ulint bits; 00426 ulint col_no; 00427 byte* old_ptr; 00428 ulint type_cmpl; 00429 byte* type_cmpl_ptr; 00430 ulint i; 00431 00432 ut_a(index->type & DICT_CLUSTERED); 00433 ut_ad(rec_offs_validate(rec, index, offsets)); 00434 ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR 00435 + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE); 00436 table = index->table; 00437 00438 first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR 00439 + TRX_UNDO_PAGE_FREE); 00440 ptr = undo_page + first_free; 00441 00442 ut_ad(first_free <= UNIV_PAGE_SIZE); 00443 00444 if (trx_undo_left(undo_page, ptr) < 50) { 00445 00446 /* NOTE: the value 50 must be big enough so that the general 00447 fields written below fit on the undo log page */ 00448 00449 return(0); 00450 } 00451 00452 /* Reserve 2 bytes for the pointer to the next undo log record */ 00453 ptr += 2; 00454 00455 /* Store first some general parameters to the undo log */ 00456 00457 if (update) { 00458 if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) { 00459 type_cmpl = TRX_UNDO_UPD_DEL_REC; 00460 } else { 00461 type_cmpl = TRX_UNDO_UPD_EXIST_REC; 00462 } 00463 } else { 00464 type_cmpl = TRX_UNDO_DEL_MARK_REC; 00465 } 00466 00467 type_cmpl = type_cmpl | (cmpl_info * TRX_UNDO_CMPL_INFO_MULT); 00468 00469 mach_write_to_1(ptr, type_cmpl); 00470 00471 type_cmpl_ptr = ptr; 00472 00473 ptr++; 00474 len = mach_dulint_write_much_compressed(ptr, trx->undo_no); 00475 ptr += len; 00476 00477 len = mach_dulint_write_much_compressed(ptr, table->id); 00478 ptr += len; 00479 00480 /*----------------------------------------*/ 00481 /* Store the state of the info bits */ 00482 00483 bits = rec_get_info_bits(rec, dict_table_is_comp(table)); 00484 mach_write_to_1(ptr, bits); 00485 ptr += 1; 00486 00487 /* Store the values of the system columns */ 00488 field = rec_get_nth_field(rec, offsets, 00489 dict_index_get_sys_col_pos(index, DATA_TRX_ID), &len); 00490 ut_ad(len == DATA_TRX_ID_LEN); 00491 trx_id = trx_read_trx_id(field); 00492 field = rec_get_nth_field(rec, offsets, 00493 dict_index_get_sys_col_pos(index, DATA_ROLL_PTR), &len); 00494 ut_ad(len == DATA_ROLL_PTR_LEN); 00495 roll_ptr = trx_read_roll_ptr(field); 00496 00497 len = mach_dulint_write_compressed(ptr, trx_id); 00498 ptr += len; 00499 00500 len = mach_dulint_write_compressed(ptr, roll_ptr); 00501 ptr += len; 00502 00503 /*----------------------------------------*/ 00504 /* Store then the fields required to uniquely determine the 00505 record which will be modified in the clustered index */ 00506 00507 for (i = 0; i < dict_index_get_n_unique(index); i++) { 00508 00509 field = rec_get_nth_field(rec, offsets, i, &flen); 00510 00511 if (trx_undo_left(undo_page, ptr) < 4) { 00512 00513 return(0); 00514 } 00515 00516 len = mach_write_compressed(ptr, flen); 00517 ptr += len; 00518 00519 if (flen != UNIV_SQL_NULL) { 00520 if (trx_undo_left(undo_page, ptr) < flen) { 00521 00522 return(0); 00523 } 00524 00525 ut_memcpy(ptr, field, flen); 00526 ptr += flen; 00527 } 00528 } 00529 00530 /*----------------------------------------*/ 00531 /* Save to the undo log the old values of the columns to be updated. */ 00532 00533 if (update) { 00534 if (trx_undo_left(undo_page, ptr) < 5) { 00535 00536 return(0); 00537 } 00538 00539 len = mach_write_compressed(ptr, upd_get_n_fields(update)); 00540 ptr += len; 00541 00542 for (i = 0; i < upd_get_n_fields(update); i++) { 00543 00544 upd_field = upd_get_nth_field(update, i); 00545 pos = upd_field->field_no; 00546 00547 /* Write field number to undo log */ 00548 if (trx_undo_left(undo_page, ptr) < 5) { 00549 00550 return(0); 00551 } 00552 00553 len = mach_write_compressed(ptr, pos); 00554 ptr += len; 00555 00556 /* Save the old value of field */ 00557 field = rec_get_nth_field(rec, offsets, pos, &flen); 00558 00559 if (trx_undo_left(undo_page, ptr) < 5) { 00560 00561 return(0); 00562 } 00563 00564 if (rec_offs_nth_extern(offsets, pos)) { 00565 /* If a field has external storage, we add 00566 to flen the flag */ 00567 00568 len = mach_write_compressed(ptr, 00569 UNIV_EXTERN_STORAGE_FIELD + flen); 00570 00571 /* Notify purge that it eventually has to 00572 free the old externally stored field */ 00573 00574 trx->update_undo->del_marks = TRUE; 00575 00576 *type_cmpl_ptr = *type_cmpl_ptr 00577 | TRX_UNDO_UPD_EXTERN; 00578 } else { 00579 len = mach_write_compressed(ptr, flen); 00580 } 00581 00582 ptr += len; 00583 00584 if (flen != UNIV_SQL_NULL) { 00585 if (trx_undo_left(undo_page, ptr) < flen) { 00586 00587 return(0); 00588 } 00589 00590 ut_memcpy(ptr, field, flen); 00591 ptr += flen; 00592 } 00593 } 00594 } 00595 00596 /*----------------------------------------*/ 00597 /* In the case of a delete marking, and also in the case of an update 00598 where any ordering field of any index changes, store the values of all 00599 columns which occur as ordering fields in any index. This info is used 00600 in the purge of old versions where we use it to build and search the 00601 delete marked index records, to look if we can remove them from the 00602 index tree. Note that starting from 4.0.14 also externally stored 00603 fields can be ordering in some index. But we always store at least 00604 384 first bytes locally to the clustered index record, which means 00605 we can construct the column prefix fields in the index from the 00606 stored data. */ 00607 00608 if (!update || !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { 00609 00610 trx->update_undo->del_marks = TRUE; 00611 00612 if (trx_undo_left(undo_page, ptr) < 5) { 00613 00614 return(0); 00615 } 00616 00617 old_ptr = ptr; 00618 00619 /* Reserve 2 bytes to write the number of bytes the stored 00620 fields take in this undo record */ 00621 00622 ptr += 2; 00623 00624 for (col_no = 0; col_no < dict_table_get_n_cols(table); 00625 col_no++) { 00626 00627 col = dict_table_get_nth_col(table, col_no); 00628 00629 if (col->ord_part > 0) { 00630 00631 pos = dict_index_get_nth_col_pos(index, 00632 col_no); 00633 00634 /* Write field number to undo log */ 00635 if (trx_undo_left(undo_page, ptr) < 5) { 00636 00637 return(0); 00638 } 00639 00640 len = mach_write_compressed(ptr, pos); 00641 ptr += len; 00642 00643 /* Save the old value of field */ 00644 field = rec_get_nth_field(rec, offsets, pos, 00645 &flen); 00646 00647 if (trx_undo_left(undo_page, ptr) < 5) { 00648 00649 return(0); 00650 } 00651 00652 len = mach_write_compressed(ptr, flen); 00653 ptr += len; 00654 00655 if (flen != UNIV_SQL_NULL) { 00656 if (trx_undo_left(undo_page, ptr) 00657 < flen) { 00658 00659 return(0); 00660 } 00661 00662 ut_memcpy(ptr, field, flen); 00663 ptr += flen; 00664 } 00665 } 00666 } 00667 00668 mach_write_to_2(old_ptr, ptr - old_ptr); 00669 } 00670 00671 /*----------------------------------------*/ 00672 /* Write pointers to the previous and the next undo log records */ 00673 if (trx_undo_left(undo_page, ptr) < 2) { 00674 00675 return(0); 00676 } 00677 00678 mach_write_to_2(ptr, first_free); 00679 ptr += 2; 00680 mach_write_to_2(undo_page + first_free, ptr - undo_page); 00681 00682 mach_write_to_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE, 00683 ptr - undo_page); 00684 00685 /* Write to the REDO log about this change in the UNDO log */ 00686 00687 trx_undof_page_add_undo_rec_log(undo_page, first_free, 00688 ptr - undo_page, mtr); 00689 return(first_free); 00690 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 73 of file trx0rec.c.
References mach_read_from_2(), mach_write_to_2(), NULL, TRX_UNDO_PAGE_FREE, TRX_UNDO_PAGE_HDR, and ut_memcpy().
Referenced by recv_parse_or_apply_log_rec_body().
00075 : end of log record or NULL */ 00076 byte* ptr, /* in: buffer */ 00077 byte* end_ptr,/* in: buffer end */ 00078 page_t* page) /* in: page or NULL */ 00079 { 00080 ulint len; 00081 byte* rec; 00082 ulint first_free; 00083 00084 if (end_ptr < ptr + 2) { 00085 00086 return(NULL); 00087 } 00088 00089 len = mach_read_from_2(ptr); 00090 ptr += 2; 00091 00092 if (end_ptr < ptr + len) { 00093 00094 return(NULL); 00095 } 00096 00097 if (page == NULL) { 00098 00099 return(ptr + len); 00100 } 00101 00102 first_free = mach_read_from_2(page + TRX_UNDO_PAGE_HDR 00103 + TRX_UNDO_PAGE_FREE); 00104 rec = page + first_free; 00105 00106 mach_write_to_2(rec, first_free + 4 + len); 00107 mach_write_to_2(rec + 2 + len, first_free); 00108 00109 mach_write_to_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE, 00110 first_free + 4 + len); 00111 ut_memcpy(rec + 2, ptr, len); 00112 00113 return(ptr + len); 00114 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* trx_undo_parse_erase_page_end | ( | byte * | ptr, | |
| byte *end_ptr | __attribute__((unused)), | |||
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 962 of file trx0rec.c.
References NULL, trx_undo_erase_page_end(), and ut_ad.
00964 : end of log record or NULL */ 00965 byte* ptr, /* in: buffer */ 00966 byte* end_ptr __attribute__((unused)), /* in: buffer end */ 00967 page_t* page, /* in: page or NULL */ 00968 mtr_t* mtr) /* in: mtr or NULL */ 00969 { 00970 ut_ad(ptr && end_ptr); 00971 00972 if (page == NULL) { 00973 00974 return(ptr); 00975 } 00976 00977 trx_undo_erase_page_end(page, mtr); 00978 00979 return(ptr); 00980 }
Here is the call graph for this function:

| ulint trx_undo_prev_version_build | ( | rec_t * | index_rec, | |
| mtr_t *index_mtr | __attribute__((unused)), | |||
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| ulint * | offsets, | |||
| mem_heap_t * | heap, | |||
| rec_t ** | old_vers | |||
| ) |
Definition at line 1245 of file trx0rec.c.
References btr_push_update_extern_fields(), buf, buf_block_align(), DB_ERROR, DB_SUCCESS, DICT_CLUSTERED, dict_index_get_n_unique(), err, index(), trx_purge_struct::latch, mem_alloc, mem_free, mem_heap_alloc(), mtr_memo_contains(), MTR_MEMO_PAGE_S_FIX, MTR_MEMO_PAGE_X_FIX, NULL, purge_sys, rec_convert_dtuple_to_rec(), rec_copy(), rec_get_converted_size(), rec_offs_make_valid(), rec_offs_n_fields(), rec_offs_size(), rec_offs_validate(), rec_print(), rec_print_new(), rec_set_field_extern_bits(), ROW_COPY_DATA, row_get_rec_roll_ptr(), row_get_rec_trx_id(), row_rec_to_index_entry(), row_upd_changes_field_size_or_external(), row_upd_index_replace_new_col_vals(), row_upd_rec_in_place(), RW_LOCK_SHARED, trx_purge_sys_print(), trx_undo_get_undo_rec(), trx_undo_rec_get_pars(), trx_undo_rec_skip_row_ref(), trx_undo_roll_ptr_is_insert(), trx_undo_update_rec_get_sys_cols(), trx_undo_update_rec_get_update(), update, ut_ad, ut_dulint_cmp(), ut_dulint_get_high(), ut_dulint_get_low(), and ut_print_buf().
01247 : DB_SUCCESS, or DB_MISSING_HISTORY if 01248 the previous version is not >= purge_view, 01249 which means that it may have been removed, 01250 DB_ERROR if corrupted record */ 01251 rec_t* index_rec,/* in: clustered index record in the 01252 index tree */ 01253 mtr_t* index_mtr __attribute__((unused)), 01254 /* in: mtr which contains the latch to 01255 index_rec page and purge_view */ 01256 rec_t* rec, /* in: version of a clustered index record */ 01257 dict_index_t* index, /* in: clustered index */ 01258 ulint* offsets,/* in: rec_get_offsets(rec, index) */ 01259 mem_heap_t* heap, /* in: memory heap from which the memory 01260 needed is allocated */ 01261 rec_t** old_vers)/* out, own: previous version, or NULL if 01262 rec is the first inserted version, or if 01263 history data has been deleted */ 01264 { 01265 trx_undo_rec_t* undo_rec; 01266 dtuple_t* entry; 01267 dulint rec_trx_id; 01268 ulint type; 01269 dulint undo_no; 01270 dulint table_id; 01271 dulint trx_id; 01272 dulint roll_ptr; 01273 dulint old_roll_ptr; 01274 upd_t* update; 01275 byte* ptr; 01276 ulint info_bits; 01277 ulint cmpl_info; 01278 ibool dummy_extern; 01279 byte* buf; 01280 ulint err; 01281 #ifdef UNIV_SYNC_DEBUG 01282 ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); 01283 #endif /* UNIV_SYNC_DEBUG */ 01284 ut_ad(mtr_memo_contains(index_mtr, buf_block_align(index_rec), 01285 MTR_MEMO_PAGE_S_FIX) || 01286 mtr_memo_contains(index_mtr, buf_block_align(index_rec), 01287 MTR_MEMO_PAGE_X_FIX)); 01288 ut_ad(rec_offs_validate(rec, index, offsets)); 01289 01290 if (!(index->type & DICT_CLUSTERED)) { 01291 fprintf(stderr, "InnoDB: Error: trying to access" 01292 " update undo rec for non-clustered index %s\n" 01293 "InnoDB: Submit a detailed bug report to" 01294 " http://bugs.mysql.com\n" 01295 "InnoDB: index record ", index->name); 01296 rec_print(stderr, index_rec, index); 01297 fputs("\n" 01298 "InnoDB: record version ", stderr); 01299 rec_print_new(stderr, rec, offsets); 01300 putc('\n', stderr); 01301 return(DB_ERROR); 01302 } 01303 01304 roll_ptr = row_get_rec_roll_ptr(rec, index, offsets); 01305 old_roll_ptr = roll_ptr; 01306 01307 *old_vers = NULL; 01308 01309 if (trx_undo_roll_ptr_is_insert(roll_ptr)) { 01310 01311 /* The record rec is the first inserted version */ 01312 01313 return(DB_SUCCESS); 01314 } 01315 01316 rec_trx_id = row_get_rec_trx_id(rec, index, offsets); 01317 01318 err = trx_undo_get_undo_rec(roll_ptr, rec_trx_id, &undo_rec, heap); 01319 01320 if (err != DB_SUCCESS) { 01321 01322 return(err); 01323 } 01324 01325 ptr = trx_undo_rec_get_pars(undo_rec, &type, &cmpl_info, 01326 &dummy_extern, &undo_no, &table_id); 01327 01328 ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, 01329 &info_bits); 01330 ptr = trx_undo_rec_skip_row_ref(ptr, index); 01331 01332 ptr = trx_undo_update_rec_get_update(ptr, index, type, trx_id, 01333 roll_ptr, info_bits, NULL, heap, &update); 01334 01335 if (ut_dulint_cmp(table_id, index->table->id) != 0) { 01336 ptr = NULL; 01337 01338 fprintf(stderr, 01339 "InnoDB: Error: trying to access update undo rec for table %s\n" 01340 "InnoDB: but the table id in the undo record is wrong\n" 01341 "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n" 01342 "InnoDB: Run also CHECK TABLE %s\n", 01343 index->table_name, index->table_name); 01344 } 01345 01346 if (ptr == NULL) { 01347 /* The record was corrupted, return an error; these printfs 01348 should catch an elusive bug in row_vers_old_has_index_entry */ 01349 01350 fprintf(stderr, 01351 "InnoDB: table %s, index %s, n_uniq %lu\n" 01352 "InnoDB: undo rec address %p, type %lu cmpl_info %lu\n" 01353 "InnoDB: undo rec table id %lu %lu, index table id %lu %lu\n" 01354 "InnoDB: dump of 150 bytes in undo rec: ", 01355 index->table_name, index->name, 01356 (ulong) dict_index_get_n_unique(index), 01357 undo_rec, (ulong) type, (ulong) cmpl_info, 01358 (ulong) ut_dulint_get_high(table_id), 01359 (ulong) ut_dulint_get_low(table_id), 01360 (ulong) ut_dulint_get_high(index->table->id), 01361 (ulong) ut_dulint_get_low(index->table->id)); 01362 ut_print_buf(stderr, undo_rec, 150); 01363 fputs("\n" 01364 "InnoDB: index record ", stderr); 01365 rec_print(stderr, index_rec, index); 01366 fputs("\n" 01367 "InnoDB: record version ", stderr); 01368 rec_print_new(stderr, rec, offsets); 01369 fprintf(stderr, "\n" 01370 "InnoDB: Record trx id %lu %lu, update rec trx id %lu %lu\n" 01371 "InnoDB: Roll ptr in rec %lu %lu, in update rec %lu %lu\n", 01372 (ulong) ut_dulint_get_high(rec_trx_id), 01373 (ulong) ut_dulint_get_low(rec_trx_id), 01374 (ulong) ut_dulint_get_high(trx_id), 01375 (ulong) ut_dulint_get_low(trx_id), 01376 (ulong) ut_dulint_get_high(old_roll_ptr), 01377 (ulong) ut_dulint_get_low(old_roll_ptr), 01378 (ulong) ut_dulint_get_high(roll_ptr), 01379 (ulong) ut_dulint_get_low(roll_ptr)); 01380 01381 trx_purge_sys_print(); 01382 return(DB_ERROR); 01383 } 01384 01385 if (row_upd_changes_field_size_or_external(index, offsets, update)) { 01386 ulint* ext_vect; 01387 ulint n_ext_vect; 01388 01389 /* We have to set the appropriate extern storage bits in the 01390 old version of the record: the extern bits in rec for those 01391 fields that update does NOT update, as well as the the bits for 01392 those fields that update updates to become externally stored 01393 fields. Store the info to ext_vect: */ 01394 01395 ext_vect = mem_alloc(sizeof(ulint) 01396 * rec_offs_n_fields(offsets)); 01397 n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, 01398 update); 01399 entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, 01400 heap); 01401 row_upd_index_replace_new_col_vals(entry, index, update, heap); 01402 01403 buf = mem_heap_alloc(heap, 01404 rec_get_converted_size(index, entry)); 01405 01406 *old_vers = rec_convert_dtuple_to_rec(buf, index, entry); 01407 01408 /* Now set the extern bits in the old version of the record */ 01409 rec_set_field_extern_bits(*old_vers, index, 01410 ext_vect, n_ext_vect, NULL); 01411 mem_free(ext_vect); 01412 } else { 01413 buf = mem_heap_alloc(heap, rec_offs_size(offsets)); 01414 *old_vers = rec_copy(buf, rec, offsets); 01415 rec_offs_make_valid(*old_vers, index, offsets); 01416 row_upd_rec_in_place(*old_vers, offsets, update); 01417 } 01418 01419 return(DB_SUCCESS); 01420 }
Here is the call graph for this function:

Definition at line 292 of file trx0rec.c.
References mach_get_compressed_size(), and mach_read_compressed().
Referenced by trx_undo_rec_get_partial_row(), trx_undo_rec_get_row_ref(), trx_undo_rec_skip_row_ref(), and trx_undo_update_rec_get_update().
00294 : remaining part of undo log record after 00295 reading these values */ 00296 byte* ptr, /* in: pointer to remaining part of undo log record */ 00297 byte** field, /* out: pointer to stored field */ 00298 ulint* len) /* out: length of the field, or UNIV_SQL_NULL */ 00299 { 00300 *len = mach_read_compressed(ptr); 00301 ptr += mach_get_compressed_size(*len); 00302 00303 *field = ptr; 00304 00305 if (*len != UNIV_SQL_NULL) { 00306 if (*len >= UNIV_EXTERN_STORAGE_FIELD) { 00307 ptr += (*len - UNIV_EXTERN_STORAGE_FIELD); 00308 } else { 00309 ptr += *len; 00310 } 00311 } 00312 00313 return(ptr); 00314 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* trx_undo_rec_get_pars | ( | trx_undo_rec_t * | undo_rec, | |
| ulint * | type, | |||
| ulint * | cmpl_info, | |||
| ibool * | updated_extern, | |||
| dulint * | undo_no, | |||
| dulint * | table_id | |||
| ) |
Definition at line 244 of file trx0rec.c.
References FALSE, mach_dulint_get_much_compressed_size(), mach_dulint_read_much_compressed(), mach_read_from_1(), TRUE, TRX_UNDO_CMPL_INFO_MULT, and TRX_UNDO_UPD_EXTERN.
Referenced by row_purge_parse_undo_rec(), row_undo_ins_parse_undo_rec(), row_undo_mod_parse_undo_rec(), and trx_undo_prev_version_build().
00246 : remaining part of undo log 00247 record after reading these values */ 00248 trx_undo_rec_t* undo_rec, /* in: undo log record */ 00249 ulint* type, /* out: undo record type: 00250 TRX_UNDO_INSERT_REC, ... */ 00251 ulint* cmpl_info, /* out: compiler info, relevant only 00252 for update type records */ 00253 ibool* updated_extern, /* out: TRUE if we updated an 00254 externally stored fild */ 00255 dulint* undo_no, /* out: undo log record number */ 00256 dulint* table_id) /* out: table id */ 00257 { 00258 byte* ptr; 00259 ulint len; 00260 ulint type_cmpl; 00261 00262 ptr = undo_rec + 2; 00263 00264 type_cmpl = mach_read_from_1(ptr); 00265 ptr++; 00266 00267 if (type_cmpl & TRX_UNDO_UPD_EXTERN) { 00268 *updated_extern = TRUE; 00269 type_cmpl -= TRX_UNDO_UPD_EXTERN; 00270 } else { 00271 *updated_extern = FALSE; 00272 } 00273 00274 *type = type_cmpl & (TRX_UNDO_CMPL_INFO_MULT - 1); 00275 *cmpl_info = type_cmpl / TRX_UNDO_CMPL_INFO_MULT; 00276 00277 *undo_no = mach_dulint_read_much_compressed(ptr); 00278 len = mach_dulint_get_much_compressed_size(*undo_no); 00279 ptr += len; 00280 00281 *table_id = mach_dulint_read_much_compressed(ptr); 00282 len = mach_dulint_get_much_compressed_size(*table_id); 00283 ptr += len; 00284 00285 return(ptr); 00286 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* trx_undo_rec_get_partial_row | ( | byte * | ptr, | |
| dict_index_t * | index, | |||
| dtuple_t ** | row, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 879 of file trx0rec.c.
References dfield_set_data(), dict_index_get_nth_col_no(), dict_table_copy_types(), dict_table_get_n_cols(), dtuple_create(), dtuple_get_nth_field(), index(), mach_read_from_2(), trx_undo_rec_get_col_val(), trx_undo_update_rec_get_field_no(), and ut_ad.
Referenced by row_purge_parse_undo_rec().
00881 : pointer to remaining part of undo 00882 record */ 00883 byte* ptr, /* in: remaining part in update undo log 00884 record of a suitable type, at the start of 00885 the stored index columns; 00886 NOTE that this copy of the undo log record must 00887 be preserved as long as the partial row is 00888 used, as we do NOT copy the data in the 00889 record! */ 00890 dict_index_t* index, /* in: clustered index */ 00891 dtuple_t** row, /* out, own: partial row */ 00892 mem_heap_t* heap) /* in: memory heap from which the memory 00893 needed is allocated */ 00894 { 00895 dfield_t* dfield; 00896 byte* field; 00897 ulint len; 00898 ulint field_no; 00899 ulint col_no; 00900 ulint row_len; 00901 ulint total_len; 00902 byte* start_ptr; 00903 ulint i; 00904 00905 ut_ad(index && ptr && row && heap); 00906 00907 row_len = dict_table_get_n_cols(index->table); 00908 00909 *row = dtuple_create(heap, row_len); 00910 00911 dict_table_copy_types(*row, index->table); 00912 00913 start_ptr = ptr; 00914 00915 total_len = mach_read_from_2(ptr); 00916 ptr += 2; 00917 00918 for (i = 0;; i++) { 00919 00920 if (ptr == start_ptr + total_len) { 00921 00922 break; 00923 } 00924 00925 ptr = trx_undo_update_rec_get_field_no(ptr, &field_no); 00926 00927 col_no = dict_index_get_nth_col_no(index, field_no); 00928 00929 ptr = trx_undo_rec_get_col_val(ptr, &field, &len); 00930 00931 dfield = dtuple_get_nth_field(*row, col_no); 00932 00933 dfield_set_data(dfield, field, len); 00934 } 00935 00936 return(ptr); 00937 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* trx_undo_rec_get_row_ref | ( | byte * | ptr, | |
| dict_index_t * | index, | |||
| dtuple_t ** | ref, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 320 of file trx0rec.c.
References dfield_set_data(), DICT_CLUSTERED, dict_index_copy_types(), dict_index_get_n_unique(), dtuple_create(), dtuple_get_nth_field(), index(), trx_undo_rec_get_col_val(), ut_a, and ut_ad.
Referenced by row_purge_parse_undo_rec(), row_undo_ins_parse_undo_rec(), and row_undo_mod_parse_undo_rec().
00322 : pointer to remaining part of undo 00323 record */ 00324 byte* ptr, /* in: remaining part of a copy of an undo log 00325 record, at the start of the row reference; 00326 NOTE that this copy of the undo log record must 00327 be preserved as long as the row reference is 00328 used, as we do NOT copy the data in the 00329 record! */ 00330 dict_index_t* index, /* in: clustered index */ 00331 dtuple_t** ref, /* out, own: row reference */ 00332 mem_heap_t* heap) /* in: memory heap from which the memory 00333 needed is allocated */ 00334 { 00335 dfield_t* dfield; 00336 byte* field; 00337 ulint len; 00338 ulint ref_len; 00339 ulint i; 00340 00341 ut_ad(index && ptr && ref && heap); 00342 ut_a(index->type & DICT_CLUSTERED); 00343 00344 ref_len = dict_index_get_n_unique(index); 00345 00346 *ref = dtuple_create(heap, ref_len); 00347 00348 dict_index_copy_types(*ref, index, ref_len); 00349 00350 for (i = 0; i < ref_len; i++) { 00351 dfield = dtuple_get_nth_field(*ref, i); 00352 00353 ptr = trx_undo_rec_get_col_val(ptr, &field, &len); 00354 00355 dfield_set_data(dfield, field, len); 00356 } 00357 00358 return(ptr); 00359 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* trx_undo_rec_skip_row_ref | ( | byte * | ptr, | |
| dict_index_t * | index | |||
| ) |
Definition at line 365 of file trx0rec.c.
References DICT_CLUSTERED, dict_index_get_n_unique(), index(), trx_undo_rec_get_col_val(), ut_a, and ut_ad.
Referenced by trx_undo_prev_version_build().
00367 : pointer to remaining part of undo 00368 record */ 00369 byte* ptr, /* in: remaining part in update undo log 00370 record, at the start of the row reference */ 00371 dict_index_t* index) /* in: clustered index */ 00372 { 00373 byte* field; 00374 ulint len; 00375 ulint ref_len; 00376 ulint i; 00377 00378 ut_ad(index && ptr); 00379 ut_a(index->type & DICT_CLUSTERED); 00380 00381 ref_len = dict_index_get_n_unique(index); 00382 00383 for (i = 0; i < ref_len; i++) { 00384 ptr = trx_undo_rec_get_col_val(ptr, &field, &len); 00385 } 00386 00387 return(ptr); 00388 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint trx_undo_report_row_operation | ( | ulint | flags, | |
| ulint | op_type, | |||
| que_thr_t * | thr, | |||
| dict_index_t * | index, | |||
| dtuple_t * | clust_entry, | |||
| upd_t * | update, | |||
| ulint | cmpl_info, | |||
| rec_t * | rec, | |||
| dulint * | roll_ptr | |||
| ) |
Definition at line 989 of file trx0rec.c.
References BTR_NO_UNDO_LOG_FLAG, BUF_GET, buf_page_get_gen(), DB_OUT_OF_FILE_SPACE, DB_SUCCESS, DICT_CLUSTERED, trx_undo_struct::empty, FALSE, FIL_NULL, trx_undo_struct::guess_page, trx_rseg_struct::id, index(), trx_struct::insert_undo, trx_undo_struct::last_page_no, mem_heap_free, mtr_commit(), mtr_start(), trx_rseg_struct::mutex, mutex_enter, mutex_exit(), NULL, offset, page_t, rec_get_offsets, REC_OFFS_NORMAL_SIZE, trx_struct::rseg, RW_X_LATCH, trx_undo_struct::space, SYNC_TRX_UNDO_PAGE, thr_get_trx(), trx_undo_struct::top_offset, trx_undo_struct::top_page_no, trx_undo_struct::top_undo_no, TRUE, trx_undo_add_page(), trx_undo_assign_undo(), trx_undo_build_roll_ptr(), trx_undo_erase_page_end(), TRX_UNDO_INSERT, TRX_UNDO_INSERT_OP, TRX_UNDO_MODIFY_OP, trx_undo_page_report_insert(), trx_undo_page_report_modify(), TRX_UNDO_UPDATE, trx_struct::undo_mutex, trx_struct::undo_no, update, trx_struct::update_undo, ut_a, ut_ad, UT_DULINT_INC, and ut_dulint_zero.
Referenced by btr_cur_del_mark_set_clust_rec(), btr_cur_ins_lock_and_undo(), and btr_cur_upd_lock_and_undo().
00991 : DB_SUCCESS or error code */ 00992 ulint flags, /* in: if BTR_NO_UNDO_LOG_FLAG bit is 00993 set, does nothing */ 00994 ulint op_type, /* in: TRX_UNDO_INSERT_OP or 00995 TRX_UNDO_MODIFY_OP */ 00996 que_thr_t* thr, /* in: query thread */ 00997 dict_index_t* index, /* in: clustered index */ 00998 dtuple_t* clust_entry, /* in: in the case of an insert, 00999 index entry to insert into the 01000 clustered index, otherwise NULL */ 01001 upd_t* update, /* in: in the case of an update, 01002 the update vector, otherwise NULL */ 01003 ulint cmpl_info, /* in: compiler info on secondary 01004 index updates */ 01005 rec_t* rec, /* in: in case of an update or delete 01006 marking, the record in the clustered 01007 index, otherwise NULL */ 01008 dulint* roll_ptr) /* out: rollback pointer to the 01009 inserted undo log record, 01010 ut_dulint_zero if BTR_NO_UNDO_LOG 01011 flag was specified */ 01012 { 01013 trx_t* trx; 01014 trx_undo_t* undo; 01015 page_t* undo_page; 01016 ulint offset; 01017 ulint page_no; 01018 ibool is_insert; 01019 trx_rseg_t* rseg; 01020 mtr_t mtr; 01021 mem_heap_t* heap = NULL; 01022 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01023 ulint* offsets = offsets_; 01024 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01025 01026 ut_a(index->type & DICT_CLUSTERED); 01027 01028 if (flags & BTR_NO_UNDO_LOG_FLAG) { 01029 01030 *roll_ptr = ut_dulint_zero; 01031 01032 return(DB_SUCCESS); 01033 } 01034 01035 ut_ad(thr); 01036 ut_ad((op_type != TRX_UNDO_INSERT_OP) 01037 || (clust_entry && !update && !rec)); 01038 01039 trx = thr_get_trx(thr); 01040 rseg = trx->rseg; 01041 01042 mutex_enter(&(trx->undo_mutex)); 01043 01044 /* If the undo log is not assigned yet, assign one */ 01045 01046 if (op_type == TRX_UNDO_INSERT_OP) { 01047 01048 if (trx->insert_undo == NULL) { 01049 01050 trx_undo_assign_undo(trx, TRX_UNDO_INSERT); 01051 } 01052 01053 undo = trx->insert_undo; 01054 is_insert = TRUE; 01055 } else { 01056 ut_ad(op_type == TRX_UNDO_MODIFY_OP); 01057 01058 if (trx->update_undo == NULL) { 01059 01060 trx_undo_assign_undo(trx, TRX_UNDO_UPDATE); 01061 01062 } 01063 01064 undo = trx->update_undo; 01065 is_insert = FALSE; 01066 } 01067 01068 if (undo == NULL) { 01069 /* Did not succeed: out of space */ 01070 mutex_exit(&(trx->undo_mutex)); 01071 01072 return(DB_OUT_OF_FILE_SPACE); 01073 } 01074 01075 page_no = undo->last_page_no; 01076 01077 mtr_start(&mtr); 01078 01079 for (;;) { 01080 undo_page = buf_page_get_gen(undo->space, page_no, 01081 RW_X_LATCH, undo->guess_page, 01082 BUF_GET, 01083 __FILE__, __LINE__, 01084 &mtr); 01085 01086 #ifdef UNIV_SYNC_DEBUG 01087 buf_page_dbg_add_level(undo_page, SYNC_TRX_UNDO_PAGE); 01088 #endif /* UNIV_SYNC_DEBUG */ 01089 01090 if (op_type == TRX_UNDO_INSERT_OP) { 01091 offset = trx_undo_page_report_insert(undo_page, trx, 01092 index, clust_entry, 01093 &mtr); 01094 } else { 01095 offsets = rec_get_offsets(rec, index, offsets, 01096 ULINT_UNDEFINED, &heap); 01097 offset = trx_undo_page_report_modify(undo_page, trx, 01098 index, rec, offsets, update, cmpl_info, &mtr); 01099 } 01100 01101 if (offset == 0) { 01102 /* The record did not fit on the page. We erase the 01103 end segment of the undo log page and write a log 01104 record of it: this is to ensure that in the debug 01105 version the replicate page constructed using the log 01106 records stays identical to the original page */ 01107 01108 trx_undo_erase_page_end(undo_page, &mtr); 01109 } 01110 01111 mtr_commit(&mtr); 01112 01113 if (offset != 0) { 01114 /* Success */ 01115 01116 break; 01117 } 01118 01119 ut_ad(page_no == undo->last_page_no); 01120 01121 /* We have to extend the undo log by one page */ 01122 01123 mtr_start(&mtr); 01124 01125 /* When we add a page to an undo log, this is analogous to 01126 a pessimistic insert in a B-tree, and we must reserve the 01127 counterpart of the tree latch, which is the rseg mutex. */ 01128 01129 mutex_enter(&(rseg->mutex)); 01130 01131 page_no = trx_undo_add_page(trx, undo, &mtr); 01132 01133 mutex_exit(&(rseg->mutex)); 01134 01135 if (page_no == FIL_NULL) { 01136 /* Did not succeed: out of space */ 01137 01138 mutex_exit(&(trx->undo_mutex)); 01139 mtr_commit(&mtr); 01140 if (UNIV_LIKELY_NULL(heap)) { 01141 mem_heap_free(heap); 01142 } 01143 return(DB_OUT_OF_FILE_SPACE); 01144 } 01145 } 01146 01147 undo->empty = FALSE; 01148 undo->top_page_no = page_no; 01149 undo->top_offset = offset; 01150 undo->top_undo_no = trx->undo_no; 01151 undo->guess_page = undo_page; 01152 01153 UT_DULINT_INC(trx->undo_no); 01154 01155 mutex_exit(&(trx->undo_mutex)); 01156 01157 *roll_ptr = trx_undo_build_roll_ptr(is_insert, rseg->id, page_no, 01158 offset); 01159 if (UNIV_LIKELY_NULL(heap)) { 01160 mem_heap_free(heap); 01161 } 01162 return(DB_SUCCESS); 01163 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 748 of file trx0rec.c.
References mach_get_compressed_size(), and mach_read_compressed().
Referenced by trx_undo_rec_get_partial_row(), and trx_undo_update_rec_get_update().
00750 : remaining part of undo log record after 00751 reading this value */ 00752 byte* ptr, /* in: pointer to remaining part of undo log record */ 00753 ulint* field_no)/* out: field number */ 00754 { 00755 *field_no = mach_read_compressed(ptr); 00756 ptr += mach_get_compressed_size(*field_no); 00757 00758 return(ptr); 00759 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 731 of file trx0rec.c.
References mach_get_compressed_size(), and mach_read_compressed().
Referenced by trx_undo_update_rec_get_update().
00733 : remaining part of undo log record after 00734 reading this value */ 00735 byte* ptr, /* in: pointer to remaining part of undo log record */ 00736 ulint* n) /* out: number of fields */ 00737 { 00738 *n = mach_read_compressed(ptr); 00739 ptr += mach_get_compressed_size(*n); 00740 00741 return(ptr); 00742 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* trx_undo_update_rec_get_sys_cols | ( | byte * | ptr, | |
| dulint * | trx_id, | |||
| dulint * | roll_ptr, | |||
| ulint * | info_bits | |||
| ) |
Definition at line 697 of file trx0rec.c.
References mach_dulint_get_compressed_size(), mach_dulint_read_compressed(), and mach_read_from_1().
Referenced by row_purge_parse_undo_rec(), row_undo_mod_parse_undo_rec(), and trx_undo_prev_version_build().
00699 : remaining part of undo log 00700 record after reading these values */ 00701 byte* ptr, /* in: remaining part of undo log 00702 record after reading general 00703 parameters */ 00704 dulint* trx_id, /* out: trx id */ 00705 dulint* roll_ptr, /* out: roll ptr */ 00706 ulint* info_bits) /* out: info bits state */ 00707 { 00708 ulint len; 00709 00710 /* Read the state of the info bits */ 00711 *info_bits = mach_read_from_1(ptr); 00712 ptr += 1; 00713 00714 /* Read the values of the system columns */ 00715 00716 *trx_id = mach_dulint_read_compressed(ptr); 00717 len = mach_dulint_get_compressed_size(*trx_id); 00718 ptr += len; 00719 00720 *roll_ptr = mach_dulint_read_compressed(ptr); 00721 len = mach_dulint_get_compressed_size(*roll_ptr); 00722 ptr += len; 00723 00724 return(ptr); 00725 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* trx_undo_update_rec_get_update | ( | byte * | ptr, | |
| dict_index_t * | index, | |||
| ulint | type, | |||
| dulint | trx_id, | |||
| dulint | roll_ptr, | |||
| ulint | info_bits, | |||
| trx_t * | trx, | |||
| mem_heap_t * | heap, | |||
| upd_t ** | upd | |||
| ) |
Definition at line 765 of file trx0rec.c.
References buf, DATA_ROLL_PTR, DATA_ROLL_PTR_LEN, DATA_TRX_ID, DATA_TRX_ID_LEN, dfield_set_data(), DICT_CLUSTERED, dict_index_get_n_fields(), dict_index_get_sys_col_pos(), dict_index_name_print(), upd_field_struct::extern_storage, index(), mem_heap_alloc(), upd_field_struct::new_val, NULL, TRUE, TRX_UNDO_DEL_MARK_REC, trx_undo_rec_get_col_val(), trx_undo_update_rec_get_field_no(), trx_undo_update_rec_get_n_upd_fields(), trx_write_roll_ptr(), trx_write_trx_id(), upd_create(), upd_field_set_field_no(), upd_get_nth_field(), update, ut_a, and ut_print_name().
Referenced by row_purge_parse_undo_rec(), row_undo_mod_parse_undo_rec(), and trx_undo_prev_version_build().
00767 : remaining part of the record, 00768 NULL if an error detected, which means that 00769 the record is corrupted */ 00770 byte* ptr, /* in: remaining part in update undo log 00771 record, after reading the row reference 00772 NOTE that this copy of the undo log record must 00773 be preserved as long as the update vector is 00774 used, as we do NOT copy the data in the 00775 record! */ 00776 dict_index_t* index, /* in: clustered index */ 00777 ulint type, /* in: TRX_UNDO_UPD_EXIST_REC, 00778 TRX_UNDO_UPD_DEL_REC, or 00779 TRX_UNDO_DEL_MARK_REC; in the last case, 00780 only trx id and roll ptr fields are added to 00781 the update vector */ 00782 dulint trx_id, /* in: transaction id from this undo record */ 00783 dulint roll_ptr,/* in: roll pointer from this undo record */ 00784 ulint info_bits,/* in: info bits from this undo record */ 00785 trx_t* trx, /* in: transaction */ 00786 mem_heap_t* heap, /* in: memory heap from which the memory 00787 needed is allocated */ 00788 upd_t** upd) /* out, own: update vector */ 00789 { 00790 upd_field_t* upd_field; 00791 upd_t* update; 00792 ulint n_fields; 00793 byte* buf; 00794 byte* field; 00795 ulint len; 00796 ulint field_no; 00797 ulint i; 00798 00799 ut_a(index->type & DICT_CLUSTERED); 00800 00801 if (type != TRX_UNDO_DEL_MARK_REC) { 00802 ptr = trx_undo_update_rec_get_n_upd_fields(ptr, &n_fields); 00803 } else { 00804 n_fields = 0; 00805 } 00806 00807 update = upd_create(n_fields + 2, heap); 00808 00809 update->info_bits = info_bits; 00810 00811 /* Store first trx id and roll ptr to update vector */ 00812 00813 upd_field = upd_get_nth_field(update, n_fields); 00814 buf = mem_heap_alloc(heap, DATA_TRX_ID_LEN); 00815 trx_write_trx_id(buf, trx_id); 00816 00817 upd_field_set_field_no(upd_field, 00818 dict_index_get_sys_col_pos(index, DATA_TRX_ID), 00819 index, trx); 00820 dfield_set_data(&(upd_field->new_val), buf, DATA_TRX_ID_LEN); 00821 00822 upd_field = upd_get_nth_field(update, n_fields + 1); 00823 buf = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN); 00824 trx_write_roll_ptr(buf, roll_ptr); 00825 00826 upd_field_set_field_no(upd_field, 00827 dict_index_get_sys_col_pos(index, DATA_ROLL_PTR), 00828 index, trx); 00829 dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN); 00830 00831 /* Store then the updated ordinary columns to the update vector */ 00832 00833 for (i = 0; i < n_fields; i++) { 00834 00835 ptr = trx_undo_update_rec_get_field_no(ptr, &field_no); 00836 00837 if (field_no >= dict_index_get_n_fields(index)) { 00838 fprintf(stderr, 00839 "InnoDB: Error: trying to access update undo rec field %lu in ", (ulong) field_no); 00840 dict_index_name_print(stderr, trx, index); 00841 fprintf(stderr, "\n" 00842 "InnoDB: but index has only %lu fields\n" 00843 "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n" 00844 "InnoDB: Run also CHECK TABLE ", 00845 (ulong) dict_index_get_n_fields(index)); 00846 ut_print_name(stderr, trx, TRUE, index->table_name); 00847 fprintf(stderr, "\n" 00848 "InnoDB: n_fields = %lu, i = %lu, ptr %p\n", 00849 (ulong) n_fields, (ulong) i, ptr); 00850 return(NULL); 00851 } 00852 00853 ptr = trx_undo_rec_get_col_val(ptr, &field, &len); 00854 00855 upd_field = upd_get_nth_field(update, i); 00856 00857 upd_field_set_field_no(upd_field, field_no, index, trx); 00858 00859 if (len != UNIV_SQL_NULL && len >= UNIV_EXTERN_STORAGE_FIELD) { 00860 00861 upd_field->extern_storage = TRUE; 00862 00863 len -= UNIV_EXTERN_STORAGE_FIELD; 00864 } 00865 00866 dfield_set_data(&(upd_field->new_val), field, len); 00867 } 00868 00869 *upd = update; 00870 00871 return(ptr); 00872 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void trx_undof_page_add_undo_rec_log | ( | page_t * | undo_page, | |
| ulint | old_free, | |||
| ulint | new_free, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 34 of file trx0rec.c.
References mach_write_to_2(), memcpy, MLOG_BUF_MARGIN, mlog_catenate_string(), mlog_close(), mlog_open(), MLOG_UNDO_INSERT, mlog_write_initial_log_record_fast(), and NULL.
Referenced by trx_undo_page_report_insert(), and trx_undo_page_report_modify().
00036 : undo log page */ 00037 ulint old_free, /* in: start offset of the inserted entry */ 00038 ulint new_free, /* in: end offset of the entry */ 00039 mtr_t* mtr) /* in: mtr */ 00040 { 00041 byte* log_ptr; 00042 const byte* log_end; 00043 ulint len; 00044 00045 log_ptr = mlog_open(mtr, 11 + 13 + MLOG_BUF_MARGIN); 00046 00047 if (log_ptr == NULL) { 00048 00049 return; 00050 } 00051 00052 log_end = &log_ptr[11 + 13 + MLOG_BUF_MARGIN]; 00053 log_ptr = mlog_write_initial_log_record_fast(undo_page, 00054 MLOG_UNDO_INSERT, log_ptr, mtr); 00055 len = new_free - old_free - 4; 00056 00057 mach_write_to_2(log_ptr, len); 00058 log_ptr += 2; 00059 00060 if (log_ptr + len <= log_end) { 00061 memcpy(log_ptr, undo_page + old_free + 2, len); 00062 mlog_close(mtr, log_ptr + len); 00063 } else { 00064 mlog_close(mtr, log_ptr); 00065 mlog_catenate_string(mtr, undo_page + old_free + 2, len); 00066 } 00067 }
Here is the call graph for this function:

Here is the caller graph for this function:

1.4.7

