#include "univ.i"#include "dict0dict.h"#include "data0data.h"#include "page0cur.h"#include "btr0types.h"#include "que0types.h"#include "row0types.h"#include "ha0ha.h"Include dependency graph for btr0cur.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
| #define BTR_CUR_BINARY 3 |
Definition at line 655 of file btr0cur.h.
Referenced by btr_cur_pessimistic_insert(), and btr_cur_search_to_nth_level().
| #define BTR_CUR_HASH 1 |
Definition at line 648 of file btr0cur.h.
Referenced by btr_cur_optimistic_insert(), btr_search_guess_on_hash(), and btr_search_update_hash_node_on_insert().
| #define BTR_CUR_HASH_FAIL 2 |
Definition at line 650 of file btr0cur.h.
Referenced by btr_search_guess_on_hash(), btr_search_info_update_slow(), and btr_search_update_hash_ref().
| #define BTR_CUR_INSERT_TO_IBUF 4 |
Definition at line 656 of file btr0cur.h.
Referenced by btr_cur_search_to_nth_level(), and row_ins_index_entry_low().
| #define BTR_CUR_PAGE_COMPRESS_LIMIT (UNIV_PAGE_SIZE / 2) |
| #define BTR_CUR_RETRY_DELETE_N_TIMES 100 |
Definition at line 662 of file btr0cur.h.
Referenced by row_purge_remove_clust_if_poss(), row_purge_remove_sec_if_poss(), row_undo_ins_remove_clust_rec(), and row_undo_ins_remove_sec().
| #define BTR_CUR_RETRY_SLEEP_TIME 50000 |
Definition at line 663 of file btr0cur.h.
Referenced by row_purge_remove_clust_if_poss(), row_purge_remove_sec_if_poss(), row_undo_ins_remove_clust_rec(), and row_undo_ins_remove_sec().
| #define BTR_EXTERN_FIELD_REF_SIZE 20 |
Definition at line 683 of file btr0cur.h.
Referenced by btr_copy_externally_stored_field(), btr_cur_mark_dtuple_inherited_extern(), btr_cur_set_ownership_of_extern_field(), btr_cur_unmark_dtuple_extern_fields(), btr_free_externally_stored_field(), btr_rec_get_externally_stored_len(), btr_store_big_rec_extern_fields(), dtuple_convert_back_big_rec(), and dtuple_convert_big_rec().
| #define BTR_EXTERN_INHERITED_FLAG 64 |
Definition at line 693 of file btr0cur.h.
Referenced by btr_cur_mark_dtuple_inherited_extern(), and btr_free_externally_stored_field().
| #define BTR_EXTERN_LEN 12 |
Definition at line 677 of file btr0cur.h.
Referenced by btr_copy_externally_stored_field(), btr_cur_mark_dtuple_inherited_extern(), btr_cur_set_ownership_of_extern_field(), btr_cur_unmark_dtuple_extern_fields(), btr_free_externally_stored_field(), btr_rec_get_externally_stored_len(), and btr_store_big_rec_extern_fields().
| #define BTR_EXTERN_OFFSET 8 |
Definition at line 675 of file btr0cur.h.
Referenced by btr_copy_externally_stored_field(), btr_free_externally_stored_field(), and btr_store_big_rec_extern_fields().
| #define BTR_EXTERN_OWNER_FLAG 128 |
Definition at line 692 of file btr0cur.h.
Referenced by btr_cur_set_ownership_of_extern_field(), btr_cur_unmark_dtuple_extern_fields(), and btr_free_externally_stored_field().
| #define BTR_EXTERN_PAGE_NO 4 |
Definition at line 674 of file btr0cur.h.
Referenced by btr_copy_externally_stored_field(), btr_free_externally_stored_field(), and btr_store_big_rec_extern_fields().
| #define BTR_EXTERN_SPACE_ID 0 |
Definition at line 673 of file btr0cur.h.
Referenced by btr_copy_externally_stored_field(), btr_free_externally_stored_field(), and btr_store_big_rec_extern_fields().
| #define BTR_KEEP_SYS_FLAG 4 |
Definition at line 24 of file btr0cur.h.
Referenced by btr_cur_del_mark_set_clust_rec(), btr_cur_ins_lock_and_undo(), btr_cur_optimistic_update(), btr_cur_parse_del_mark_set_clust_rec(), btr_cur_parse_update_in_place(), btr_cur_pessimistic_update(), btr_cur_update_in_place(), btr_insert_on_non_leaf_level(), row_ins_sec_index_entry_by_modify(), row_undo_mod_clust_low(), and row_undo_mod_del_unmark_sec_and_undo_update().
| #define BTR_NO_LOCKING_FLAG 2 |
Definition at line 23 of file btr0cur.h.
Referenced by btr_cur_optimistic_insert(), btr_cur_pessimistic_insert(), btr_cur_pessimistic_update(), btr_cur_upd_lock_and_undo(), btr_insert_on_non_leaf_level(), ibuf_insert_low(), lock_clust_rec_modify_check_and_lock(), lock_clust_rec_read_check_and_lock(), lock_rec_insert_check_and_lock(), lock_sec_rec_modify_check_and_lock(), lock_sec_rec_read_check_and_lock(), lock_table(), row_undo_mod_clust_low(), row_undo_mod_del_mark_or_remove_sec_low(), row_undo_mod_del_unmark_sec_and_undo_update(), row_upd_clust_rec(), row_upd_clust_rec_by_insert(), row_upd_del_mark_clust_rec(), and row_upd_in_place_in_select().
| #define BTR_NO_UNDO_LOG_FLAG 1 |
Definition at line 22 of file btr0cur.h.
Referenced by btr_cur_pessimistic_insert(), btr_cur_pessimistic_update(), btr_insert_on_non_leaf_level(), ibuf_insert_low(), row_undo_mod_clust_low(), and trx_undo_report_row_operation().
| #define BTR_PATH_ARRAY_N_SLOTS 250 |
Definition at line 578 of file btr0cur.h.
Referenced by btr_cur_add_path_info(), and btr_estimate_n_rows_in_range().
| typedef struct btr_path_struct btr_path_t |
| byte* btr_copy_externally_stored_field | ( | ulint * | len, | |
| byte * | data, | |||
| ulint | local_len, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 3731 of file btr0cur.c.
References btr_blob_get_next_page_no(), btr_blob_get_part_len(), BTR_BLOB_HDR_SIZE, BTR_EXTERN_FIELD_REF_SIZE, BTR_EXTERN_LEN, BTR_EXTERN_OFFSET, BTR_EXTERN_PAGE_NO, BTR_EXTERN_SPACE_ID, buf, buf_page_get, FIL_NULL, FIL_PAGE_DATA, mach_read_from_4(), mem_heap_alloc(), mtr_commit(), mtr_start(), offset, page, page_t, RW_S_LATCH, SYNC_EXTERN_STORAGE, ut_a, and ut_memcpy().
Referenced by btr_rec_copy_externally_stored_field().
03733 : the whole field copied to heap */ 03734 ulint* len, /* out: length of the whole field */ 03735 byte* data, /* in: 'internally' stored part of the 03736 field containing also the reference to 03737 the external part */ 03738 ulint local_len,/* in: length of data */ 03739 mem_heap_t* heap) /* in: mem heap */ 03740 { 03741 page_t* page; 03742 ulint space_id; 03743 ulint page_no; 03744 ulint offset; 03745 ulint extern_len; 03746 byte* blob_header; 03747 ulint part_len; 03748 byte* buf; 03749 ulint copied_len; 03750 mtr_t mtr; 03751 03752 ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); 03753 03754 local_len -= BTR_EXTERN_FIELD_REF_SIZE; 03755 03756 space_id = mach_read_from_4(data + local_len + BTR_EXTERN_SPACE_ID); 03757 03758 page_no = mach_read_from_4(data + local_len + BTR_EXTERN_PAGE_NO); 03759 03760 offset = mach_read_from_4(data + local_len + BTR_EXTERN_OFFSET); 03761 03762 /* Currently a BLOB cannot be bigger that 4 GB; we 03763 leave the 4 upper bytes in the length field unused */ 03764 03765 extern_len = mach_read_from_4(data + local_len + BTR_EXTERN_LEN + 4); 03766 03767 buf = mem_heap_alloc(heap, local_len + extern_len); 03768 03769 ut_memcpy(buf, data, local_len); 03770 copied_len = local_len; 03771 03772 if (extern_len == 0) { 03773 *len = copied_len; 03774 03775 return(buf); 03776 } 03777 03778 for (;;) { 03779 mtr_start(&mtr); 03780 03781 page = buf_page_get(space_id, page_no, RW_S_LATCH, &mtr); 03782 #ifdef UNIV_SYNC_DEBUG 03783 buf_page_dbg_add_level(page, SYNC_EXTERN_STORAGE); 03784 #endif /* UNIV_SYNC_DEBUG */ 03785 blob_header = page + offset; 03786 03787 part_len = btr_blob_get_part_len(blob_header); 03788 03789 ut_memcpy(buf + copied_len, blob_header + BTR_BLOB_HDR_SIZE, 03790 part_len); 03791 copied_len += part_len; 03792 03793 page_no = btr_blob_get_next_page_no(blob_header); 03794 03795 mtr_commit(&mtr); 03796 03797 if (page_no == FIL_NULL) { 03798 ut_a(copied_len == local_len + extern_len); 03799 03800 *len = copied_len; 03801 03802 return(buf); 03803 } 03804 03805 /* On other BLOB pages except the first the BLOB header 03806 always is at the page data start: */ 03807 03808 offset = FIL_PAGE_DATA; 03809 03810 ut_a(copied_len < local_len + extern_len); 03811 } 03812 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2386 of file btr0cur.c.
References btr_compress(), btr_cur_get_page(), btr_cur_get_rec(), btr_cur_get_tree(), btr_page_get_level(), buf_block_align(), dict_tree_get_lock(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, MTR_MEMO_X_LOCK, and ut_ad.
02388 : cursor on the page to compress; 02389 cursor does not stay valid */ 02390 mtr_t* mtr) /* in: mtr */ 02391 { 02392 ut_ad(mtr_memo_contains(mtr, 02393 dict_tree_get_lock(btr_cur_get_tree(cursor)), 02394 MTR_MEMO_X_LOCK)); 02395 ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_rec(cursor)), 02396 MTR_MEMO_PAGE_X_FIX)); 02397 ut_ad(btr_page_get_level(btr_cur_get_page(cursor), mtr) == 0); 02398 02399 btr_compress(cursor, mtr); 02400 }
Here is the call graph for this function:

Definition at line 2410 of file btr0cur.c.
References btr_compress(), btr_cur_get_rec(), btr_cur_get_tree(), buf_block_align(), dict_tree_get_lock(), FALSE, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, MTR_MEMO_X_LOCK, TRUE, and ut_ad.
Referenced by btr_cur_pessimistic_delete(), btr_cur_pessimistic_update(), and btr_node_ptr_delete().
02412 : TRUE if compression occurred */ 02413 btr_cur_t* cursor, /* in: cursor on the page to compress; 02414 cursor does not stay valid if compression 02415 occurs */ 02416 mtr_t* mtr) /* in: mtr */ 02417 { 02418 ut_ad(mtr_memo_contains(mtr, 02419 dict_tree_get_lock(btr_cur_get_tree(cursor)), 02420 MTR_MEMO_X_LOCK)); 02421 ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_rec(cursor)), 02422 MTR_MEMO_PAGE_X_FIX)); 02423 02424 if (btr_cur_compress_recommendation(cursor, mtr)) { 02425 02426 btr_compress(cursor, mtr); 02427 02428 return(TRUE); 02429 } 02430 02431 return(FALSE); 02432 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint btr_cur_del_mark_set_clust_rec | ( | ulint | flags, | |
| btr_cur_t * | cursor, | |||
| ibool | val, | |||
| que_thr_t * | thr, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 2144 of file btr0cur.c.
References yaSSL::block, btr_cur_del_mark_set_clust_rec_log(), btr_cur_get_rec(), BTR_KEEP_SYS_FLAG, btr_search_latch, buf_block_align(), DB_SUCCESS, DICT_CLUSTERED, dict_table_is_comp(), err, btr_cur_struct::index, index(), lock_clust_rec_modify_check_and_lock(), mem_heap_free, NULL, page_rec_is_comp(), rec_get_deleted_flag(), rec_get_offsets, rec_offs_comp(), REC_OFFS_NORMAL_SIZE, rec_print_new(), rec_set_deleted_flag(), row_upd_rec_sys_fields(), rw_lock_x_lock, rw_lock_x_unlock, thr_get_trx(), TRX_UNDO_MODIFY_OP, trx_undo_report_row_operation(), and ut_ad.
Referenced by row_upd_clust_rec_by_insert(), and row_upd_del_mark_clust_rec().
02146 : DB_SUCCESS, DB_LOCK_WAIT, or error 02147 number */ 02148 ulint flags, /* in: undo logging and locking flags */ 02149 btr_cur_t* cursor, /* in: cursor */ 02150 ibool val, /* in: value to set */ 02151 que_thr_t* thr, /* in: query thread */ 02152 mtr_t* mtr) /* in: mtr */ 02153 { 02154 dict_index_t* index; 02155 buf_block_t* block; 02156 dulint roll_ptr; 02157 ulint err; 02158 rec_t* rec; 02159 trx_t* trx; 02160 mem_heap_t* heap = NULL; 02161 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 02162 ulint* offsets = offsets_; 02163 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 02164 02165 rec = btr_cur_get_rec(cursor); 02166 index = cursor->index; 02167 ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); 02168 offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); 02169 02170 #ifdef UNIV_DEBUG 02171 if (btr_cur_print_record_ops && thr) { 02172 btr_cur_trx_report(thr_get_trx(thr), index, "del mark "); 02173 rec_print_new(stderr, rec, offsets); 02174 } 02175 #endif /* UNIV_DEBUG */ 02176 02177 ut_ad(index->type & DICT_CLUSTERED); 02178 ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); 02179 02180 err = lock_clust_rec_modify_check_and_lock(flags, 02181 rec, index, offsets, thr); 02182 02183 if (err != DB_SUCCESS) { 02184 02185 if (UNIV_LIKELY_NULL(heap)) { 02186 mem_heap_free(heap); 02187 } 02188 return(err); 02189 } 02190 02191 err = trx_undo_report_row_operation(flags, TRX_UNDO_MODIFY_OP, thr, 02192 index, NULL, NULL, 0, rec, 02193 &roll_ptr); 02194 if (err != DB_SUCCESS) { 02195 02196 if (UNIV_LIKELY_NULL(heap)) { 02197 mem_heap_free(heap); 02198 } 02199 return(err); 02200 } 02201 02202 block = buf_block_align(rec); 02203 02204 if (block->is_hashed) { 02205 rw_lock_x_lock(&btr_search_latch); 02206 } 02207 02208 rec_set_deleted_flag(rec, rec_offs_comp(offsets), val); 02209 02210 trx = thr_get_trx(thr); 02211 02212 if (!(flags & BTR_KEEP_SYS_FLAG)) { 02213 row_upd_rec_sys_fields(rec, index, offsets, trx, roll_ptr); 02214 } 02215 02216 if (block->is_hashed) { 02217 rw_lock_x_unlock(&btr_search_latch); 02218 } 02219 02220 btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx, 02221 roll_ptr, mtr); 02222 if (UNIV_LIKELY_NULL(heap)) { 02223 mem_heap_free(heap); 02224 } 02225 return(DB_SUCCESS); 02226 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint btr_cur_del_mark_set_sec_rec | ( | ulint | flags, | |
| btr_cur_t * | cursor, | |||
| ibool | val, | |||
| que_thr_t * | thr, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 2307 of file btr0cur.c.
References yaSSL::block, btr_cur_del_mark_set_sec_rec_log(), btr_cur_get_rec(), btr_search_latch, buf_block_align(), buf_block_get_frame(), DB_SUCCESS, dict_table_is_comp(), err, btr_cur_struct::index, lock_sec_rec_modify_check_and_lock(), page_is_comp(), rec_print(), rec_set_deleted_flag(), rw_lock_x_lock, rw_lock_x_unlock, dict_index_struct::table, thr_get_trx(), and ut_ad.
Referenced by row_undo_mod_del_mark_or_remove_sec_low(), row_undo_mod_del_unmark_sec_and_undo_update(), and row_upd_sec_index_entry().
02309 : DB_SUCCESS, DB_LOCK_WAIT, or error 02310 number */ 02311 ulint flags, /* in: locking flag */ 02312 btr_cur_t* cursor, /* in: cursor */ 02313 ibool val, /* in: value to set */ 02314 que_thr_t* thr, /* in: query thread */ 02315 mtr_t* mtr) /* in: mtr */ 02316 { 02317 buf_block_t* block; 02318 rec_t* rec; 02319 ulint err; 02320 02321 rec = btr_cur_get_rec(cursor); 02322 02323 #ifdef UNIV_DEBUG 02324 if (btr_cur_print_record_ops && thr) { 02325 btr_cur_trx_report(thr_get_trx(thr), cursor->index, 02326 "del mark "); 02327 rec_print(stderr, rec, cursor->index); 02328 } 02329 #endif /* UNIV_DEBUG */ 02330 02331 err = lock_sec_rec_modify_check_and_lock(flags, rec, cursor->index, 02332 thr); 02333 if (err != DB_SUCCESS) { 02334 02335 return(err); 02336 } 02337 02338 block = buf_block_align(rec); 02339 ut_ad(!!page_is_comp(buf_block_get_frame(block)) 02340 == dict_table_is_comp(cursor->index->table)); 02341 02342 if (block->is_hashed) { 02343 rw_lock_x_lock(&btr_search_latch); 02344 } 02345 02346 rec_set_deleted_flag(rec, page_is_comp(buf_block_get_frame(block)), 02347 val); 02348 02349 if (block->is_hashed) { 02350 rw_lock_x_unlock(&btr_search_latch); 02351 } 02352 02353 btr_cur_del_mark_set_sec_rec_log(rec, val, mtr); 02354 02355 return(DB_SUCCESS); 02356 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2363 of file btr0cur.c.
References btr_cur_del_mark_set_sec_rec_log(), buf_frame_align(), FALSE, page_is_comp(), and rec_set_deleted_flag().
Referenced by ibuf_insert_to_index_page().
02365 : record to delete unmark */ 02366 mtr_t* mtr) /* in: mtr */ 02367 { 02368 /* We do not need to reserve btr_search_latch, as the page has just 02369 been read to the buffer pool and there cannot be a hash index to it. */ 02370 02371 rec_set_deleted_flag(rec, page_is_comp(buf_frame_align(rec)), FALSE); 02372 02373 btr_cur_del_mark_set_sec_rec_log(rec, FALSE, mtr); 02374 }
Here is the call graph for this function:

Here is the caller graph for this function:

Referenced by btr_compress(), btr_cur_compress(), btr_cur_insert_if_possible(), btr_cur_optimistic_delete(), btr_cur_optimistic_insert(), btr_cur_optimistic_update(), btr_cur_pessimistic_delete(), btr_cur_pessimistic_insert(), btr_cur_pessimistic_update(), btr_discard_page(), btr_estimate_number_of_different_key_vals(), btr_page_get_split_rec_to_left(), btr_page_get_split_rec_to_right(), btr_page_get_sure_split_rec(), btr_page_insert_fits(), btr_page_split_and_insert(), btr_pcur_release_leaf(), btr_pcur_restore_position(), btr_root_raise_and_insert(), and row_ins_index_entry_low().
Here is the caller graph for this function:

| UNIV_INLINE page_cur_t* btr_cur_get_page_cur | ( | btr_cur_t * | cursor | ) |
Referenced by btr_cur_insert_if_possible(), btr_cur_open_at_index_side(), btr_cur_open_at_rnd_pos(), btr_cur_optimistic_delete(), btr_cur_optimistic_insert(), btr_cur_optimistic_update(), btr_cur_pessimistic_delete(), btr_cur_pessimistic_update(), btr_cur_search_to_nth_level(), btr_page_split_and_insert(), and btr_root_raise_and_insert().
Here is the caller graph for this function:

Referenced by btr_cur_add_path_info(), btr_cur_compress(), btr_cur_compress_if_useful(), btr_cur_del_mark_set_clust_rec(), btr_cur_del_mark_set_sec_rec(), btr_cur_ins_lock_and_undo(), btr_cur_optimistic_delete(), btr_cur_optimistic_update(), btr_cur_pessimistic_delete(), btr_cur_pessimistic_update(), btr_cur_upd_lock_and_undo(), btr_cur_update_in_place(), btr_page_get_father_for_rec(), btr_page_get_split_rec_to_left(), btr_page_get_split_rec_to_right(), btr_page_get_sure_split_rec(), btr_page_insert_fits(), btr_page_split_and_insert(), btr_search_check_guess(), btr_search_guess_on_hash(), btr_search_info_update_slow(), btr_search_update_hash_node_on_insert(), btr_search_update_hash_on_delete(), btr_search_update_hash_on_insert(), btr_search_update_hash_ref(), row_ins_clust_index_entry_by_modify(), row_ins_duplicate_error_in_clust(), row_ins_index_entry_low(), row_ins_must_modify(), row_ins_sec_index_entry_by_modify(), row_undo_mod_del_unmark_sec_and_undo_update(), row_upd_clust_rec(), row_upd_clust_rec_by_insert(), and row_upd_sec_index_entry().
Here is the caller graph for this function:

| UNIV_INLINE dict_tree_t* btr_cur_get_tree | ( | btr_cur_t * | cursor | ) |
Referenced by btr_compress(), btr_cur_compress(), btr_cur_compress_if_useful(), btr_cur_pessimistic_delete(), btr_cur_pessimistic_insert(), btr_discard_page(), btr_page_split_and_insert(), btr_pcur_restore_position(), btr_pcur_store_position(), and btr_root_raise_and_insert().
Here is the caller graph for this function:

| UNIV_INLINE void btr_cur_invalidate | ( | btr_cur_t * | cursor | ) |
| void btr_cur_mark_dtuple_inherited_extern | ( | dtuple_t * | entry, | |
| ulint * | ext_vec, | |||
| ulint | n_ext_vec, | |||
| upd_t * | update | |||
| ) |
Definition at line 3138 of file btr0cur.c.
References BTR_EXTERN_FIELD_REF_SIZE, BTR_EXTERN_INHERITED_FLAG, BTR_EXTERN_LEN, data, dfield_get_data(), dfield_get_len(), dtuple_get_nth_field(), FALSE, mach_read_from_1(), mach_write_to_1(), NULL, TRUE, upd_get_n_fields(), upd_get_nth_field(), and update.
Referenced by row_upd_clust_rec_by_insert().
03140 : updated entry to be inserted to 03141 clustered index */ 03142 ulint* ext_vec, /* in: array of extern fields in the 03143 original record */ 03144 ulint n_ext_vec, /* in: number of elements in ext_vec */ 03145 upd_t* update) /* in: update vector */ 03146 { 03147 dfield_t* dfield; 03148 ulint byte_val; 03149 byte* data; 03150 ulint len; 03151 ibool is_updated; 03152 ulint j; 03153 ulint i; 03154 03155 if (ext_vec == NULL) { 03156 03157 return; 03158 } 03159 03160 for (i = 0; i < n_ext_vec; i++) { 03161 03162 /* Check ext_vec[i] is in updated fields */ 03163 is_updated = FALSE; 03164 03165 for (j = 0; j < upd_get_n_fields(update); j++) { 03166 if (upd_get_nth_field(update, j)->field_no 03167 == ext_vec[i]) { 03168 is_updated = TRUE; 03169 } 03170 } 03171 03172 if (!is_updated) { 03173 dfield = dtuple_get_nth_field(entry, ext_vec[i]); 03174 03175 data = (byte*) dfield_get_data(dfield); 03176 len = dfield_get_len(dfield); 03177 03178 len -= BTR_EXTERN_FIELD_REF_SIZE; 03179 03180 byte_val = mach_read_from_1(data + len 03181 + BTR_EXTERN_LEN); 03182 03183 byte_val = byte_val | BTR_EXTERN_INHERITED_FLAG; 03184 03185 mach_write_to_1(data + len + BTR_EXTERN_LEN, byte_val); 03186 } 03187 } 03188 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_cur_mark_extern_inherited_fields | ( | rec_t * | rec, | |
| const ulint * | offsets, | |||
| upd_t * | update, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 3092 of file btr0cur.c.
References btr_cur_set_ownership_of_extern_field(), FALSE, n, NULL, rec_get_node_ptr_flag(), rec_offs_comp(), rec_offs_n_fields(), rec_offs_nth_extern(), rec_offs_validate(), TRUE, upd_get_n_fields(), upd_get_nth_field(), update, and ut_ad.
Referenced by row_upd_clust_rec_by_insert().
03094 : record in a clustered index */ 03095 const ulint* offsets,/* in: array returned by rec_get_offsets() */ 03096 upd_t* update, /* in: update vector */ 03097 mtr_t* mtr) /* in: mtr */ 03098 { 03099 ibool is_updated; 03100 ulint n; 03101 ulint j; 03102 ulint i; 03103 03104 ut_ad(rec_offs_validate(rec, NULL, offsets)); 03105 ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec)); 03106 n = rec_offs_n_fields(offsets); 03107 03108 for (i = 0; i < n; i++) { 03109 if (rec_offs_nth_extern(offsets, i)) { 03110 03111 /* Check it is not in updated fields */ 03112 is_updated = FALSE; 03113 03114 if (update) { 03115 for (j = 0; j < upd_get_n_fields(update); 03116 j++) { 03117 if (upd_get_nth_field(update, j) 03118 ->field_no == i) { 03119 is_updated = TRUE; 03120 } 03121 } 03122 } 03123 03124 if (!is_updated) { 03125 btr_cur_set_ownership_of_extern_field(rec, 03126 offsets, i, FALSE, mtr); 03127 } 03128 } 03129 } 03130 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_cur_open_at_index_side | ( | ibool | from_left, | |
| dict_index_t * | index, | |||
| ulint | latch_mode, | |||
| btr_cur_t * | cursor, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 585 of file btr0cur.c.
References BTR_CONT_MODIFY_TREE, btr_cur_add_path_info(), btr_cur_get_page_cur(), btr_cur_latch_leaves(), BTR_ESTIMATE, BTR_MODIFY_TREE, btr_node_ptr_get_child_page_no(), btr_page_get_index_id(), btr_page_get_level(), buf_block_align(), BUF_GET, buf_page_get_gen(), buf_block_struct::check_index_page_at_flush, dict_tree_get_lock(), dict_tree_get_page(), dict_tree_get_space(), dict_tree_struct::id, btr_cur_struct::index, index(), mem_heap_free, mtr_release_s_latch_at_savepoint(), mtr_s_lock, mtr_set_savepoint(), mtr_x_lock, NULL, page, page_cur_get_rec(), page_cur_move_to_next(), page_cur_move_to_prev(), page_cur_set_after_last(), page_cur_set_before_first(), page_t, rec_get_offsets, REC_OFFS_NORMAL_SIZE, RW_NO_LATCH, TRUE, ut_ad, and ut_dulint_cmp().
Referenced by btr_estimate_n_rows_in_range(), and btr_pcur_restore_position().
00587 : TRUE if open to the low end, 00588 FALSE if to the high end */ 00589 dict_index_t* index, /* in: index */ 00590 ulint latch_mode, /* in: latch mode */ 00591 btr_cur_t* cursor, /* in: cursor */ 00592 mtr_t* mtr) /* in: mtr */ 00593 { 00594 page_cur_t* page_cursor; 00595 dict_tree_t* tree; 00596 page_t* page; 00597 ulint page_no; 00598 ulint space; 00599 ulint height; 00600 ulint root_height = 0; /* remove warning */ 00601 rec_t* node_ptr; 00602 ulint estimate; 00603 ulint savepoint; 00604 mem_heap_t* heap = NULL; 00605 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 00606 ulint* offsets = offsets_; 00607 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 00608 00609 estimate = latch_mode & BTR_ESTIMATE; 00610 latch_mode = latch_mode & ~BTR_ESTIMATE; 00611 00612 tree = index->tree; 00613 00614 /* Store the position of the tree latch we push to mtr so that we 00615 know how to release it when we have latched the leaf node */ 00616 00617 savepoint = mtr_set_savepoint(mtr); 00618 00619 if (latch_mode == BTR_MODIFY_TREE) { 00620 mtr_x_lock(dict_tree_get_lock(tree), mtr); 00621 } else { 00622 mtr_s_lock(dict_tree_get_lock(tree), mtr); 00623 } 00624 00625 page_cursor = btr_cur_get_page_cur(cursor); 00626 cursor->index = index; 00627 00628 space = dict_tree_get_space(tree); 00629 page_no = dict_tree_get_page(tree); 00630 00631 height = ULINT_UNDEFINED; 00632 00633 for (;;) { 00634 page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, 00635 BUF_GET, 00636 __FILE__, __LINE__, 00637 mtr); 00638 ut_ad(0 == ut_dulint_cmp(tree->id, 00639 btr_page_get_index_id(page))); 00640 00641 buf_block_align(page)->check_index_page_at_flush = TRUE; 00642 00643 if (height == ULINT_UNDEFINED) { 00644 /* We are in the root node */ 00645 00646 height = btr_page_get_level(page, mtr); 00647 root_height = height; 00648 } 00649 00650 if (height == 0) { 00651 btr_cur_latch_leaves(page, space, page_no, 00652 latch_mode, cursor, mtr); 00653 00654 /* In versions <= 3.23.52 we had forgotten to 00655 release the tree latch here. If in an index scan 00656 we had to scan far to find a record visible to the 00657 current transaction, that could starve others 00658 waiting for the tree latch. */ 00659 00660 if ((latch_mode != BTR_MODIFY_TREE) 00661 && (latch_mode != BTR_CONT_MODIFY_TREE)) { 00662 00663 /* Release the tree s-latch */ 00664 00665 mtr_release_s_latch_at_savepoint( 00666 mtr, savepoint, 00667 dict_tree_get_lock(tree)); 00668 } 00669 } 00670 00671 if (from_left) { 00672 page_cur_set_before_first(page, page_cursor); 00673 } else { 00674 page_cur_set_after_last(page, page_cursor); 00675 } 00676 00677 if (height == 0) { 00678 if (estimate) { 00679 btr_cur_add_path_info(cursor, height, 00680 root_height); 00681 } 00682 00683 break; 00684 } 00685 00686 ut_ad(height > 0); 00687 00688 if (from_left) { 00689 page_cur_move_to_next(page_cursor); 00690 } else { 00691 page_cur_move_to_prev(page_cursor); 00692 } 00693 00694 if (estimate) { 00695 btr_cur_add_path_info(cursor, height, root_height); 00696 } 00697 00698 height--; 00699 00700 node_ptr = page_cur_get_rec(page_cursor); 00701 offsets = rec_get_offsets(node_ptr, cursor->index, offsets, 00702 ULINT_UNDEFINED, &heap); 00703 /* Go to the child node */ 00704 page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); 00705 } 00706 00707 if (UNIV_LIKELY_NULL(heap)) { 00708 mem_heap_free(heap); 00709 } 00710 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_cur_open_at_rnd_pos | ( | dict_index_t * | index, | |
| ulint | latch_mode, | |||
| btr_cur_t * | cursor, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 716 of file btr0cur.c.
References btr_cur_get_page_cur(), btr_cur_latch_leaves(), BTR_MODIFY_TREE, btr_node_ptr_get_child_page_no(), btr_page_get_index_id(), btr_page_get_level(), BUF_GET, buf_page_get_gen(), dict_tree_get_lock(), dict_tree_get_page(), dict_tree_get_space(), dict_tree_struct::id, btr_cur_struct::index, index(), mem_heap_free, mtr_s_lock, mtr_x_lock, NULL, page, page_cur_get_rec(), page_cur_open_on_rnd_user_rec(), page_t, rec_get_offsets, REC_OFFS_NORMAL_SIZE, RW_NO_LATCH, ut_ad, and ut_dulint_cmp().
Referenced by btr_estimate_number_of_different_key_vals().
00718 : index */ 00719 ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */ 00720 btr_cur_t* cursor, /* in/out: B-tree cursor */ 00721 mtr_t* mtr) /* in: mtr */ 00722 { 00723 page_cur_t* page_cursor; 00724 dict_tree_t* tree; 00725 page_t* page; 00726 ulint page_no; 00727 ulint space; 00728 ulint height; 00729 rec_t* node_ptr; 00730 mem_heap_t* heap = NULL; 00731 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 00732 ulint* offsets = offsets_; 00733 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 00734 00735 tree = index->tree; 00736 00737 if (latch_mode == BTR_MODIFY_TREE) { 00738 mtr_x_lock(dict_tree_get_lock(tree), mtr); 00739 } else { 00740 mtr_s_lock(dict_tree_get_lock(tree), mtr); 00741 } 00742 00743 page_cursor = btr_cur_get_page_cur(cursor); 00744 cursor->index = index; 00745 00746 space = dict_tree_get_space(tree); 00747 page_no = dict_tree_get_page(tree); 00748 00749 height = ULINT_UNDEFINED; 00750 00751 for (;;) { 00752 page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, 00753 BUF_GET, 00754 __FILE__, __LINE__, 00755 mtr); 00756 ut_ad(0 == ut_dulint_cmp(tree->id, 00757 btr_page_get_index_id(page))); 00758 00759 if (height == ULINT_UNDEFINED) { 00760 /* We are in the root node */ 00761 00762 height = btr_page_get_level(page, mtr); 00763 } 00764 00765 if (height == 0) { 00766 btr_cur_latch_leaves(page, space, page_no, 00767 latch_mode, cursor, mtr); 00768 } 00769 00770 page_cur_open_on_rnd_user_rec(page, page_cursor); 00771 00772 if (height == 0) { 00773 00774 break; 00775 } 00776 00777 ut_ad(height > 0); 00778 00779 height--; 00780 00781 node_ptr = page_cur_get_rec(page_cursor); 00782 offsets = rec_get_offsets(node_ptr, cursor->index, offsets, 00783 ULINT_UNDEFINED, &heap); 00784 /* Go to the child node */ 00785 page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); 00786 } 00787 00788 if (UNIV_LIKELY_NULL(heap)) { 00789 mem_heap_free(heap); 00790 } 00791 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2440 of file btr0cur.c.
References btr_cur_get_page(), btr_cur_get_page_cur(), btr_cur_get_rec(), btr_page_get_level(), btr_search_update_hash_on_delete(), buf_block_align(), ibuf_update_free_bits_low(), btr_cur_struct::index, lock_update_delete(), mem_heap_free, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, NULL, page, page_cur_delete_rec(), page_get_max_insert_size_after_reorganize(), page_t, rec_get_offsets, rec_offs_any_extern(), REC_OFFS_NORMAL_SIZE, rec_offs_size(), and ut_ad.
Referenced by ibuf_delete_rec(), row_purge_remove_clust_if_poss_low(), row_purge_remove_sec_if_poss_low(), row_undo_ins_remove_clust_rec(), row_undo_ins_remove_sec_low(), row_undo_mod_del_mark_or_remove_sec_low(), and row_undo_mod_remove_clust_low().
02442 : TRUE if success, i.e., the page 02443 did not become too empty */ 02444 btr_cur_t* cursor, /* in: cursor on leaf page, on the record to 02445 delete; cursor stays valid: if deletion 02446 succeeds, on function exit it points to the 02447 successor of the deleted record */ 02448 mtr_t* mtr) /* in: mtr */ 02449 { 02450 page_t* page; 02451 ulint max_ins_size; 02452 rec_t* rec; 02453 mem_heap_t* heap = NULL; 02454 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 02455 ulint* offsets = offsets_; 02456 ibool no_compress_needed; 02457 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 02458 02459 ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_rec(cursor)), 02460 MTR_MEMO_PAGE_X_FIX)); 02461 /* This is intended only for leaf page deletions */ 02462 02463 page = btr_cur_get_page(cursor); 02464 02465 ut_ad(btr_page_get_level(page, mtr) == 0); 02466 02467 rec = btr_cur_get_rec(cursor); 02468 offsets = rec_get_offsets(rec, cursor->index, offsets, 02469 ULINT_UNDEFINED, &heap); 02470 02471 no_compress_needed = !rec_offs_any_extern(offsets) 02472 && btr_cur_can_delete_without_compress( 02473 cursor, rec_offs_size(offsets), mtr); 02474 02475 if (no_compress_needed) { 02476 02477 lock_update_delete(rec); 02478 02479 btr_search_update_hash_on_delete(cursor); 02480 02481 max_ins_size = page_get_max_insert_size_after_reorganize(page, 02482 1); 02483 page_cur_delete_rec(btr_cur_get_page_cur(cursor), 02484 cursor->index, offsets, mtr); 02485 02486 ibuf_update_free_bits_low(cursor->index, page, max_ins_size, 02487 mtr); 02488 } 02489 02490 if (UNIV_LIKELY_NULL(heap)) { 02491 mem_heap_free(heap); 02492 } 02493 02494 return(no_compress_needed); 02495 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint btr_cur_optimistic_insert | ( | ulint | flags, | |
| btr_cur_t * | cursor, | |||
| dtuple_t * | entry, | |||
| rec_t ** | rec, | |||
| big_rec_t ** | big_rec, | |||
| que_thr_t * | thr, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 933 of file btr0cur.c.
References btr_cur_get_page(), btr_cur_get_page_cur(), BTR_CUR_HASH, btr_cur_ins_lock_and_undo(), BTR_CUR_PAGE_REORGANIZE_LIMIT, BTR_NO_LOCKING_FLAG, btr_page_get_level(), btr_page_get_split_rec_to_left(), btr_page_get_split_rec_to_right(), btr_page_reorganize(), btr_search_update_hash_node_on_insert(), btr_search_update_hash_on_insert(), buf_block_align(), DB_FAIL, DB_SUCCESS, DB_TOO_BIG_RECORD, DICT_CLUSTERED, dict_index_name_print(), dict_tree_get_space_reserve(), dtuple_check_typed_no_assert(), dtuple_convert_back_big_rec(), dtuple_convert_big_rec(), dtuple_print(), err, FALSE, btr_cur_struct::flag, ibuf_update_free_bits_if_full(), btr_cur_struct::index, index(), lock_update_insert(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, NULL, page, page_cur_insert_rec_low(), PAGE_CUR_LE, page_cur_search(), page_cur_tuple_insert(), PAGE_DIR_SLOT_SIZE, page_get_free_space_of_empty(), page_get_max_insert_size(), page_get_max_insert_size_after_reorganize(), page_get_n_recs(), page_is_comp(), page_t, rec_get_converted_size(), REC_MAX_DATA_SIZE, thr_get_trx(), TRUE, ut_ad, ut_error, and ut_min().
Referenced by btr_cur_pessimistic_insert(), ibuf_insert_low(), and row_ins_index_entry_low().
00935 : DB_SUCCESS, DB_WAIT_LOCK, 00936 DB_FAIL, or error number */ 00937 ulint flags, /* in: undo logging and locking flags: if not 00938 zero, the parameters index and thr should be 00939 specified */ 00940 btr_cur_t* cursor, /* in: cursor on page after which to insert; 00941 cursor stays valid */ 00942 dtuple_t* entry, /* in: entry to insert */ 00943 rec_t** rec, /* out: pointer to inserted record if 00944 succeed */ 00945 big_rec_t** big_rec,/* out: big rec vector whose fields have to 00946 be stored externally by the caller, or 00947 NULL */ 00948 que_thr_t* thr, /* in: query thread or NULL */ 00949 mtr_t* mtr) /* in: mtr */ 00950 { 00951 big_rec_t* big_rec_vec = NULL; 00952 dict_index_t* index; 00953 page_cur_t* page_cursor; 00954 page_t* page; 00955 ulint max_size; 00956 rec_t* dummy_rec; 00957 ulint level; 00958 ibool reorg; 00959 ibool inherit; 00960 ulint rec_size; 00961 ulint type; 00962 ulint err; 00963 00964 *big_rec = NULL; 00965 00966 page = btr_cur_get_page(cursor); 00967 index = cursor->index; 00968 00969 if (!dtuple_check_typed_no_assert(entry)) { 00970 fputs("InnoDB: Error in a tuple to insert into ", stderr); 00971 dict_index_name_print(stderr, thr_get_trx(thr), index); 00972 } 00973 #ifdef UNIV_DEBUG 00974 if (btr_cur_print_record_ops && thr) { 00975 btr_cur_trx_report(thr_get_trx(thr), index, "insert into "); 00976 dtuple_print(stderr, entry); 00977 } 00978 #endif /* UNIV_DEBUG */ 00979 00980 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 00981 MTR_MEMO_PAGE_X_FIX)); 00982 max_size = page_get_max_insert_size_after_reorganize(page, 1); 00983 level = btr_page_get_level(page, mtr); 00984 00985 calculate_sizes_again: 00986 /* Calculate the record size when entry is converted to a record */ 00987 rec_size = rec_get_converted_size(index, entry); 00988 00989 if (rec_size >= 00990 ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2, 00991 REC_MAX_DATA_SIZE)) { 00992 00993 /* The record is so big that we have to store some fields 00994 externally on separate database pages */ 00995 00996 big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0); 00997 00998 if (big_rec_vec == NULL) { 00999 01000 return(DB_TOO_BIG_RECORD); 01001 } 01002 01003 goto calculate_sizes_again; 01004 } 01005 01006 /* If there have been many consecutive inserts, and we are on the leaf 01007 level, check if we have to split the page to reserve enough free space 01008 for future updates of records. */ 01009 01010 type = index->type; 01011 01012 if ((type & DICT_CLUSTERED) 01013 && (dict_tree_get_space_reserve(index->tree) + rec_size > max_size) 01014 && (page_get_n_recs(page) >= 2) 01015 && (0 == level) 01016 && (btr_page_get_split_rec_to_right(cursor, &dummy_rec) 01017 || btr_page_get_split_rec_to_left(cursor, &dummy_rec))) { 01018 01019 if (big_rec_vec) { 01020 dtuple_convert_back_big_rec(index, entry, big_rec_vec); 01021 } 01022 01023 return(DB_FAIL); 01024 } 01025 01026 if (!(((max_size >= rec_size) 01027 && (max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT)) 01028 || (page_get_max_insert_size(page, 1) >= rec_size) 01029 || (page_get_n_recs(page) <= 1))) { 01030 01031 if (big_rec_vec) { 01032 dtuple_convert_back_big_rec(index, entry, big_rec_vec); 01033 } 01034 return(DB_FAIL); 01035 } 01036 01037 /* Check locks and write to the undo log, if specified */ 01038 err = btr_cur_ins_lock_and_undo(flags, cursor, entry, thr, &inherit); 01039 01040 if (err != DB_SUCCESS) { 01041 01042 if (big_rec_vec) { 01043 dtuple_convert_back_big_rec(index, entry, big_rec_vec); 01044 } 01045 return(err); 01046 } 01047 01048 page_cursor = btr_cur_get_page_cur(cursor); 01049 01050 reorg = FALSE; 01051 01052 /* Now, try the insert */ 01053 01054 *rec = page_cur_insert_rec_low(page_cursor, entry, index, 01055 NULL, NULL, mtr); 01056 if (UNIV_UNLIKELY(!(*rec))) { 01057 /* If the record did not fit, reorganize */ 01058 btr_page_reorganize(page, index, mtr); 01059 01060 ut_ad(page_get_max_insert_size(page, 1) == max_size); 01061 01062 reorg = TRUE; 01063 01064 page_cur_search(page, index, entry, PAGE_CUR_LE, page_cursor); 01065 01066 *rec = page_cur_tuple_insert(page_cursor, entry, index, mtr); 01067 01068 if (UNIV_UNLIKELY(!*rec)) { 01069 fputs("InnoDB: Error: cannot insert tuple ", stderr); 01070 dtuple_print(stderr, entry); 01071 fputs(" into ", stderr); 01072 dict_index_name_print(stderr, thr_get_trx(thr), index); 01073 fprintf(stderr, "\nInnoDB: max insert size %lu\n", 01074 (ulong) max_size); 01075 ut_error; 01076 } 01077 } 01078 01079 #ifdef BTR_CUR_HASH_ADAPT 01080 if (!reorg && (0 == level) && (cursor->flag == BTR_CUR_HASH)) { 01081 btr_search_update_hash_node_on_insert(cursor); 01082 } else { 01083 btr_search_update_hash_on_insert(cursor); 01084 } 01085 #endif 01086 01087 if (!(flags & BTR_NO_LOCKING_FLAG) && inherit) { 01088 01089 lock_update_insert(*rec); 01090 } 01091 01092 /* fprintf(stderr, "Insert into page %lu, max ins size %lu," 01093 " rec %lu ind type %lu\n", 01094 buf_frame_get_page_no(page), max_size, 01095 rec_size + PAGE_DIR_SLOT_SIZE, type); 01096 */ 01097 if (!(type & DICT_CLUSTERED)) { 01098 /* We have added a record to page: update its free bits */ 01099 ibuf_update_free_bits_if_full(cursor->index, page, max_size, 01100 rec_size + PAGE_DIR_SLOT_SIZE); 01101 } 01102 01103 *big_rec = big_rec_vec; 01104 01105 return(DB_SUCCESS); 01106 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint btr_cur_optimistic_update | ( | ulint | flags, | |
| btr_cur_t * | cursor, | |||
| upd_t * | update, | |||
| ulint | cmpl_info, | |||
| que_thr_t * | thr, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 1543 of file btr0cur.c.
References btr_cur_get_page(), btr_cur_get_page_cur(), btr_cur_get_rec(), btr_cur_insert_if_possible(), BTR_CUR_PAGE_COMPRESS_LIMIT, BTR_CUR_PAGE_REORGANIZE_LIMIT, btr_cur_unmark_extern_fields(), btr_cur_upd_lock_and_undo(), btr_cur_update_in_place(), BTR_KEEP_SYS_FLAG, btr_search_update_hash_on_delete(), buf_block_align(), DATA_ROLL_PTR, DATA_TRX_ID, DB_OVERFLOW, DB_SUCCESS, DB_UNDERFLOW, dict_table_is_comp(), err, FALSE, trx_struct::id, btr_cur_struct::index, index(), lock_rec_restore_from_page_infimum(), lock_rec_store_on_page_infimum(), mem_heap_create, mem_heap_free, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, NULL, page, page_cur_delete_rec(), page_cur_move_to_next(), page_cur_move_to_prev(), page_get_data_size(), page_get_free_space_of_empty(), page_get_max_insert_size_after_reorganize(), page_get_n_recs(), page_is_comp(), page_rec_is_comp(), page_t, rec_get_converted_size(), rec_get_deleted_flag(), rec_get_offsets, rec_offs_any_extern(), rec_offs_size(), rec_print_new(), ROW_COPY_DATA, row_rec_to_index_entry(), row_upd_changes_field_size_or_external(), row_upd_index_entry_sys_field(), row_upd_index_replace_new_col_vals_index_pos(), thr_get_trx(), upd_get_n_fields(), upd_get_nth_field(), update, ut_a, and ut_ad.
Referenced by btr_cur_pessimistic_update(), row_ins_clust_index_entry_by_modify(), row_ins_sec_index_entry_by_modify(), row_undo_mod_clust_low(), row_undo_mod_del_unmark_sec_and_undo_update(), and row_upd_clust_rec().
01545 : DB_SUCCESS, or DB_OVERFLOW if the 01546 updated record does not fit, DB_UNDERFLOW 01547 if the page would become too empty */ 01548 ulint flags, /* in: undo logging and locking flags */ 01549 btr_cur_t* cursor, /* in: cursor on the record to update; 01550 cursor stays valid and positioned on the 01551 same record */ 01552 upd_t* update, /* in: update vector; this must also 01553 contain trx id and roll ptr fields */ 01554 ulint cmpl_info,/* in: compiler info on secondary index 01555 updates */ 01556 que_thr_t* thr, /* in: query thread */ 01557 mtr_t* mtr) /* in: mtr */ 01558 { 01559 dict_index_t* index; 01560 page_cur_t* page_cursor; 01561 ulint err; 01562 page_t* page; 01563 rec_t* rec; 01564 ulint max_size; 01565 ulint new_rec_size; 01566 ulint old_rec_size; 01567 dtuple_t* new_entry; 01568 dulint roll_ptr; 01569 trx_t* trx; 01570 mem_heap_t* heap; 01571 ibool reorganized = FALSE; 01572 ulint i; 01573 ulint* offsets; 01574 01575 page = btr_cur_get_page(cursor); 01576 rec = btr_cur_get_rec(cursor); 01577 index = cursor->index; 01578 ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); 01579 01580 heap = mem_heap_create(1024); 01581 offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); 01582 01583 #ifdef UNIV_DEBUG 01584 if (btr_cur_print_record_ops && thr) { 01585 btr_cur_trx_report(thr_get_trx(thr), index, "update "); 01586 rec_print_new(stderr, rec, offsets); 01587 } 01588 #endif /* UNIV_DEBUG */ 01589 01590 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 01591 MTR_MEMO_PAGE_X_FIX)); 01592 if (!row_upd_changes_field_size_or_external(index, offsets, update)) { 01593 01594 /* The simplest and the most common case: the update does not 01595 change the size of any field and none of the updated fields is 01596 externally stored in rec or update */ 01597 mem_heap_free(heap); 01598 return(btr_cur_update_in_place(flags, cursor, update, 01599 cmpl_info, thr, mtr)); 01600 } 01601 01602 for (i = 0; i < upd_get_n_fields(update); i++) { 01603 if (upd_get_nth_field(update, i)->extern_storage) { 01604 01605 /* Externally stored fields are treated in pessimistic 01606 update */ 01607 01608 mem_heap_free(heap); 01609 return(DB_OVERFLOW); 01610 } 01611 } 01612 01613 if (rec_offs_any_extern(offsets)) { 01614 /* Externally stored fields are treated in pessimistic 01615 update */ 01616 01617 mem_heap_free(heap); 01618 return(DB_OVERFLOW); 01619 } 01620 01621 page_cursor = btr_cur_get_page_cur(cursor); 01622 01623 new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); 01624 01625 row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, 01626 FALSE, NULL); 01627 old_rec_size = rec_offs_size(offsets); 01628 new_rec_size = rec_get_converted_size(index, new_entry); 01629 01630 if (UNIV_UNLIKELY(new_rec_size >= page_get_free_space_of_empty( 01631 page_is_comp(page)) / 2)) { 01632 01633 mem_heap_free(heap); 01634 01635 return(DB_OVERFLOW); 01636 } 01637 01638 max_size = old_rec_size 01639 + page_get_max_insert_size_after_reorganize(page, 1); 01640 01641 if (UNIV_UNLIKELY(page_get_data_size(page) 01642 - old_rec_size + new_rec_size 01643 < BTR_CUR_PAGE_COMPRESS_LIMIT)) { 01644 01645 /* The page would become too empty */ 01646 01647 mem_heap_free(heap); 01648 01649 return(DB_UNDERFLOW); 01650 } 01651 01652 if (!(((max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT) 01653 && (max_size >= new_rec_size)) 01654 || (page_get_n_recs(page) <= 1))) { 01655 01656 /* There was not enough space, or it did not pay to 01657 reorganize: for simplicity, we decide what to do assuming a 01658 reorganization is needed, though it might not be necessary */ 01659 01660 mem_heap_free(heap); 01661 01662 return(DB_OVERFLOW); 01663 } 01664 01665 /* Do lock checking and undo logging */ 01666 err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info, thr, 01667 &roll_ptr); 01668 if (err != DB_SUCCESS) { 01669 01670 mem_heap_free(heap); 01671 01672 return(err); 01673 } 01674 01675 /* Ok, we may do the replacement. Store on the page infimum the 01676 explicit locks on rec, before deleting rec (see the comment in 01677 .._pessimistic_update). */ 01678 01679 lock_rec_store_on_page_infimum(page, rec); 01680 01681 btr_search_update_hash_on_delete(cursor); 01682 01683 page_cur_delete_rec(page_cursor, index, offsets, mtr); 01684 01685 page_cur_move_to_prev(page_cursor); 01686 01687 trx = thr_get_trx(thr); 01688 01689 if (!(flags & BTR_KEEP_SYS_FLAG)) { 01690 row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR, 01691 roll_ptr); 01692 row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID, 01693 trx->id); 01694 } 01695 01696 rec = btr_cur_insert_if_possible(cursor, new_entry, &reorganized, mtr); 01697 01698 ut_a(rec); /* <- We calculated above the insert would fit */ 01699 01700 if (!rec_get_deleted_flag(rec, page_is_comp(page))) { 01701 /* The new inserted record owns its possible externally 01702 stored fields */ 01703 01704 offsets = rec_get_offsets(rec, index, offsets, 01705 ULINT_UNDEFINED, &heap); 01706 btr_cur_unmark_extern_fields(rec, mtr, offsets); 01707 } 01708 01709 /* Restore the old explicit lock state on the record */ 01710 01711 lock_rec_restore_from_page_infimum(rec, page); 01712 01713 page_cur_move_to_next(page_cursor); 01714 01715 mem_heap_free(heap); 01716 01717 return(DB_SUCCESS); 01718 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* btr_cur_parse_del_mark_set_clust_rec | ( | byte * | ptr, | |
| byte * | end_ptr, | |||
| dict_index_t * | index, | |||
| page_t * | page | |||
| ) |
Definition at line 2064 of file btr0cur.c.
References BTR_KEEP_SYS_FLAG, dict_table_is_comp(), flags, index(), mach_read_from_1(), mach_read_from_2(), mem_heap_free, NULL, offset, page_is_comp(), pos(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, rec_set_deleted_flag(), row_upd_parse_sys_vals(), row_upd_rec_sys_fields_in_recovery(), UNIV_PAGE_SIZE, ut_a, and ut_ad.
Referenced by recv_parse_or_apply_log_rec_body().
02066 : end of log record or NULL */ 02067 byte* ptr, /* in: buffer */ 02068 byte* end_ptr,/* in: buffer end */ 02069 dict_index_t* index, /* in: index corresponding to page */ 02070 page_t* page) /* in: page or NULL */ 02071 { 02072 ulint flags; 02073 ulint val; 02074 ulint pos; 02075 dulint trx_id; 02076 dulint roll_ptr; 02077 ulint offset; 02078 rec_t* rec; 02079 02080 ut_ad(!page 02081 || !!page_is_comp(page) == dict_table_is_comp(index->table)); 02082 02083 if (end_ptr < ptr + 2) { 02084 02085 return(NULL); 02086 } 02087 02088 flags = mach_read_from_1(ptr); 02089 ptr++; 02090 val = mach_read_from_1(ptr); 02091 ptr++; 02092 02093 ptr = row_upd_parse_sys_vals(ptr, end_ptr, &pos, &trx_id, &roll_ptr); 02094 02095 if (ptr == NULL) { 02096 02097 return(NULL); 02098 } 02099 02100 if (end_ptr < ptr + 2) { 02101 02102 return(NULL); 02103 } 02104 02105 offset = mach_read_from_2(ptr); 02106 ptr += 2; 02107 02108 ut_a(offset <= UNIV_PAGE_SIZE); 02109 02110 if (page) { 02111 rec = page + offset; 02112 02113 if (!(flags & BTR_KEEP_SYS_FLAG)) { 02114 mem_heap_t* heap = NULL; 02115 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 02116 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 02117 02118 row_upd_rec_sys_fields_in_recovery(rec, 02119 rec_get_offsets(rec, index, offsets_, 02120 ULINT_UNDEFINED, &heap), 02121 pos, trx_id, roll_ptr); 02122 if (UNIV_LIKELY_NULL(heap)) { 02123 mem_heap_free(heap); 02124 } 02125 } 02126 02127 /* We do not need to reserve btr_search_latch, as the page 02128 is only being recovered, and there cannot be a hash index to 02129 it. */ 02130 02131 rec_set_deleted_flag(rec, page_is_comp(page), val); 02132 } 02133 02134 return(ptr); 02135 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2266 of file btr0cur.c.
References mach_read_from_1(), mach_read_from_2(), NULL, offset, page_is_comp(), rec_set_deleted_flag(), UNIV_PAGE_SIZE, and ut_a.
Referenced by recv_parse_or_apply_log_rec_body().
02268 : end of log record or NULL */ 02269 byte* ptr, /* in: buffer */ 02270 byte* end_ptr,/* in: buffer end */ 02271 page_t* page) /* in: page or NULL */ 02272 { 02273 ulint val; 02274 ulint offset; 02275 rec_t* rec; 02276 02277 if (end_ptr < ptr + 3) { 02278 02279 return(NULL); 02280 } 02281 02282 val = mach_read_from_1(ptr); 02283 ptr++; 02284 02285 offset = mach_read_from_2(ptr); 02286 ptr += 2; 02287 02288 ut_a(offset <= UNIV_PAGE_SIZE); 02289 02290 if (page) { 02291 rec = page + offset; 02292 02293 /* We do not need to reserve btr_search_latch, as the page 02294 is only being recovered, and there cannot be a hash index to 02295 it. */ 02296 02297 rec_set_deleted_flag(rec, page_is_comp(page), val); 02298 } 02299 02300 return(ptr); 02301 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* btr_cur_parse_update_in_place | ( | byte * | ptr, | |
| byte * | end_ptr, | |||
| page_t * | page, | |||
| dict_index_t * | index | |||
| ) |
Definition at line 1358 of file btr0cur.c.
References BTR_KEEP_SYS_FLAG, dict_table_is_comp(), flags, index(), mach_read_from_1(), mach_read_from_2(), mem_heap_create, mem_heap_free, NULL, page_is_comp(), pos(), rec_get_offsets, row_upd_index_parse(), row_upd_parse_sys_vals(), row_upd_rec_in_place(), row_upd_rec_sys_fields_in_recovery(), UNIV_PAGE_SIZE, update, and ut_a.
Referenced by recv_parse_or_apply_log_rec_body().
01360 : end of log record or NULL */ 01361 byte* ptr, /* in: buffer */ 01362 byte* end_ptr,/* in: buffer end */ 01363 page_t* page, /* in: page or NULL */ 01364 dict_index_t* index) /* in: index corresponding to page */ 01365 { 01366 ulint flags; 01367 rec_t* rec; 01368 upd_t* update; 01369 ulint pos; 01370 dulint trx_id; 01371 dulint roll_ptr; 01372 ulint rec_offset; 01373 mem_heap_t* heap; 01374 ulint* offsets; 01375 01376 if (end_ptr < ptr + 1) { 01377 01378 return(NULL); 01379 } 01380 01381 flags = mach_read_from_1(ptr); 01382 ptr++; 01383 01384 ptr = row_upd_parse_sys_vals(ptr, end_ptr, &pos, &trx_id, &roll_ptr); 01385 01386 if (ptr == NULL) { 01387 01388 return(NULL); 01389 } 01390 01391 if (end_ptr < ptr + 2) { 01392 01393 return(NULL); 01394 } 01395 01396 rec_offset = mach_read_from_2(ptr); 01397 ptr += 2; 01398 01399 ut_a(rec_offset <= UNIV_PAGE_SIZE); 01400 01401 heap = mem_heap_create(256); 01402 01403 ptr = row_upd_index_parse(ptr, end_ptr, heap, &update); 01404 01405 if (!ptr || !page) { 01406 01407 goto func_exit; 01408 } 01409 01410 ut_a((ibool)!!page_is_comp(page) == dict_table_is_comp(index->table)); 01411 rec = page + rec_offset; 01412 01413 /* We do not need to reserve btr_search_latch, as the page is only 01414 being recovered, and there cannot be a hash index to it. */ 01415 01416 offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); 01417 01418 if (!(flags & BTR_KEEP_SYS_FLAG)) { 01419 row_upd_rec_sys_fields_in_recovery(rec, offsets, 01420 pos, trx_id, roll_ptr); 01421 } 01422 01423 row_upd_rec_in_place(rec, offsets, update); 01424 01425 func_exit: 01426 mem_heap_free(heap); 01427 01428 return(ptr); 01429 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool btr_cur_pessimistic_delete | ( | ulint * | err, | |
| ibool | has_reserved_extents, | |||
| btr_cur_t * | cursor, | |||
| ibool | in_rollback, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 2506 of file btr0cur.c.
References btr_cur_compress_if_useful(), btr_cur_get_page(), btr_cur_get_page_cur(), btr_cur_get_rec(), btr_cur_get_tree(), btr_discard_page(), btr_insert_on_non_leaf_level(), btr_node_ptr_delete(), btr_page_get_level(), btr_page_get_prev(), btr_rec_free_externally_stored_fields(), btr_search_update_hash_on_delete(), btr_set_min_rec_mark(), buf_block_align(), buf_frame_get_page_no(), DB_OUT_OF_FILE_SPACE, DB_SUCCESS, dict_tree_build_node_ptr(), dict_tree_get_lock(), dict_tree_get_page(), FALSE, FIL_NULL, fil_space_release_free_extents(), FSP_CLEANING, fsp_reserve_free_extents(), btr_cur_struct::index, lock_update_delete(), mem_heap_create, mem_heap_free, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, MTR_MEMO_X_LOCK, NULL, page, page_cur_delete_rec(), page_get_infimum_rec(), page_get_n_recs(), page_is_comp(), page_rec_get_next(), page_t, rec_get_1byte_offs_flag(), rec_get_node_ptr_flag(), rec_get_offsets, dict_index_struct::space, btr_cur_struct::tree_height, TRUE, and ut_ad.
Referenced by btr_node_ptr_delete(), ibuf_delete_rec(), row_purge_remove_clust_if_poss_low(), row_purge_remove_sec_if_poss_low(), row_undo_ins_remove_clust_rec(), row_undo_ins_remove_sec_low(), row_undo_mod_del_mark_or_remove_sec_low(), and row_undo_mod_remove_clust_low().
02508 : TRUE if compression occurred */ 02509 ulint* err, /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE; 02510 the latter may occur because we may have 02511 to update node pointers on upper levels, 02512 and in the case of variable length keys 02513 these may actually grow in size */ 02514 ibool has_reserved_extents, /* in: TRUE if the 02515 caller has already reserved enough free 02516 extents so that he knows that the operation 02517 will succeed */ 02518 btr_cur_t* cursor, /* in: cursor on the record to delete; 02519 if compression does not occur, the cursor 02520 stays valid: it points to successor of 02521 deleted record on function exit */ 02522 ibool in_rollback,/* in: TRUE if called in rollback */ 02523 mtr_t* mtr) /* in: mtr */ 02524 { 02525 page_t* page; 02526 dict_tree_t* tree; 02527 rec_t* rec; 02528 dtuple_t* node_ptr; 02529 ulint n_extents = 0; 02530 ulint n_reserved; 02531 ibool success; 02532 ibool ret = FALSE; 02533 ulint level; 02534 mem_heap_t* heap; 02535 ulint* offsets; 02536 02537 page = btr_cur_get_page(cursor); 02538 tree = btr_cur_get_tree(cursor); 02539 02540 ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), 02541 MTR_MEMO_X_LOCK)); 02542 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 02543 MTR_MEMO_PAGE_X_FIX)); 02544 if (!has_reserved_extents) { 02545 /* First reserve enough free space for the file segments 02546 of the index tree, so that the node pointer updates will 02547 not fail because of lack of space */ 02548 02549 n_extents = cursor->tree_height / 32 + 1; 02550 02551 success = fsp_reserve_free_extents(&n_reserved, 02552 cursor->index->space, 02553 n_extents, FSP_CLEANING, mtr); 02554 if (!success) { 02555 *err = DB_OUT_OF_FILE_SPACE; 02556 02557 return(FALSE); 02558 } 02559 } 02560 02561 heap = mem_heap_create(1024); 02562 rec = btr_cur_get_rec(cursor); 02563 02564 offsets = rec_get_offsets(rec, cursor->index, 02565 NULL, ULINT_UNDEFINED, &heap); 02566 02567 /* Free externally stored fields if the record is neither 02568 a node pointer nor in two-byte format. 02569 This avoids an unnecessary loop. */ 02570 if (page_is_comp(page) 02571 ? !rec_get_node_ptr_flag(rec) 02572 : !rec_get_1byte_offs_flag(rec)) { 02573 btr_rec_free_externally_stored_fields(cursor->index, 02574 rec, offsets, in_rollback, mtr); 02575 } 02576 02577 if (UNIV_UNLIKELY(page_get_n_recs(page) < 2) 02578 && UNIV_UNLIKELY(dict_tree_get_page(btr_cur_get_tree(cursor)) 02579 != buf_frame_get_page_no(page))) { 02580 02581 /* If there is only one record, drop the whole page in 02582 btr_discard_page, if this is not the root page */ 02583 02584 btr_discard_page(cursor, mtr); 02585 02586 *err = DB_SUCCESS; 02587 ret = TRUE; 02588 02589 goto return_after_reservations; 02590 } 02591 02592 lock_update_delete(rec); 02593 level = btr_page_get_level(page, mtr); 02594 02595 if (level > 0 02596 && UNIV_UNLIKELY(rec == page_rec_get_next( 02597 page_get_infimum_rec(page)))) { 02598 02599 rec_t* next_rec = page_rec_get_next(rec); 02600 02601 if (btr_page_get_prev(page, mtr) == FIL_NULL) { 02602 02603 /* If we delete the leftmost node pointer on a 02604 non-leaf level, we must mark the new leftmost node 02605 pointer as the predefined minimum record */ 02606 02607 btr_set_min_rec_mark(next_rec, page_is_comp(page), 02608 mtr); 02609 } else { 02610 /* Otherwise, if we delete the leftmost node pointer 02611 on a page, we have to change the father node pointer 02612 so that it is equal to the new leftmost node pointer 02613 on the page */ 02614 02615 btr_node_ptr_delete(tree, page, mtr); 02616 02617 node_ptr = dict_tree_build_node_ptr( 02618 tree, next_rec, 02619 buf_frame_get_page_no(page), 02620 heap, level); 02621 02622 btr_insert_on_non_leaf_level(tree, 02623 level + 1, node_ptr, mtr); 02624 } 02625 } 02626 02627 btr_search_update_hash_on_delete(cursor); 02628 02629 page_cur_delete_rec(btr_cur_get_page_cur(cursor), cursor->index, 02630 offsets, mtr); 02631 02632 ut_ad(btr_check_node_ptr(tree, page, mtr)); 02633 02634 *err = DB_SUCCESS; 02635 02636 return_after_reservations: 02637 mem_heap_free(heap); 02638 02639 if (ret == FALSE) { 02640 ret = btr_cur_compress_if_useful(cursor, mtr); 02641 } 02642 02643 if (n_extents > 0) { 02644 fil_space_release_free_extents(cursor->index->space, 02645 n_reserved); 02646 } 02647 02648 return(ret); 02649 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint btr_cur_pessimistic_insert | ( | ulint | flags, | |
| btr_cur_t * | cursor, | |||
| dtuple_t * | entry, | |||
| rec_t ** | rec, | |||
| big_rec_t ** | big_rec, | |||
| que_thr_t * | thr, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 1115 of file btr0cur.c.
References BTR_CUR_BINARY, btr_cur_get_page(), btr_cur_get_tree(), btr_cur_ins_lock_and_undo(), btr_cur_optimistic_insert(), btr_cur_position(), BTR_NO_LOCKING_FLAG, BTR_NO_UNDO_LOG_FLAG, btr_page_split_and_insert(), btr_root_raise_and_insert(), btr_search_update_hash_on_insert(), buf_block_align(), buf_frame_get_page_no(), DB_FAIL, DB_OUT_OF_FILE_SPACE, DB_SUCCESS, DB_TOO_BIG_RECORD, dict_tree_get_lock(), dict_tree_get_page(), dtuple_check_typed(), dtuple_convert_big_rec(), err, fil_space_release_free_extents(), btr_cur_struct::flag, FSP_NORMAL, fsp_reserve_free_extents(), btr_cur_struct::index, index(), lock_update_insert(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, MTR_MEMO_X_LOCK, NULL, page, page_get_free_space_of_empty(), page_is_comp(), page_rec_get_prev(), page_t, rec_get_converted_size(), REC_MAX_DATA_SIZE, btr_cur_struct::tree_height, ut_ad, and ut_min().
Referenced by btr_cur_pessimistic_update(), btr_insert_on_non_leaf_level(), ibuf_insert_low(), and row_ins_index_entry_low().
01117 : DB_SUCCESS or error number */ 01118 ulint flags, /* in: undo logging and locking flags: if not 01119 zero, the parameter thr should be 01120 specified; if no undo logging is specified, 01121 then the caller must have reserved enough 01122 free extents in the file space so that the 01123 insertion will certainly succeed */ 01124 btr_cur_t* cursor, /* in: cursor after which to insert; 01125 cursor stays valid */ 01126 dtuple_t* entry, /* in: entry to insert */ 01127 rec_t** rec, /* out: pointer to inserted record if 01128 succeed */ 01129 big_rec_t** big_rec,/* out: big rec vector whose fields have to 01130 be stored externally by the caller, or 01131 NULL */ 01132 que_thr_t* thr, /* in: query thread or NULL */ 01133 mtr_t* mtr) /* in: mtr */ 01134 { 01135 dict_index_t* index = cursor->index; 01136 big_rec_t* big_rec_vec = NULL; 01137 page_t* page; 01138 ulint err; 01139 ibool dummy_inh; 01140 ibool success; 01141 ulint n_extents = 0; 01142 ulint n_reserved; 01143 01144 ut_ad(dtuple_check_typed(entry)); 01145 01146 *big_rec = NULL; 01147 01148 page = btr_cur_get_page(cursor); 01149 01150 ut_ad(mtr_memo_contains(mtr, 01151 dict_tree_get_lock(btr_cur_get_tree(cursor)), 01152 MTR_MEMO_X_LOCK)); 01153 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 01154 MTR_MEMO_PAGE_X_FIX)); 01155 01156 /* Try first an optimistic insert; reset the cursor flag: we do not 01157 assume anything of how it was positioned */ 01158 01159 cursor->flag = BTR_CUR_BINARY; 01160 01161 err = btr_cur_optimistic_insert(flags, cursor, entry, rec, big_rec, 01162 thr, mtr); 01163 if (err != DB_FAIL) { 01164 01165 return(err); 01166 } 01167 01168 /* Retry with a pessimistic insert. Check locks and write to undo log, 01169 if specified */ 01170 01171 err = btr_cur_ins_lock_and_undo(flags, cursor, entry, thr, &dummy_inh); 01172 01173 if (err != DB_SUCCESS) { 01174 01175 return(err); 01176 } 01177 01178 if (!(flags & BTR_NO_UNDO_LOG_FLAG)) { 01179 /* First reserve enough free space for the file segments 01180 of the index tree, so that the insert will not fail because 01181 of lack of space */ 01182 01183 n_extents = cursor->tree_height / 16 + 3; 01184 01185 success = fsp_reserve_free_extents(&n_reserved, index->space, 01186 n_extents, FSP_NORMAL, mtr); 01187 if (!success) { 01188 err = DB_OUT_OF_FILE_SPACE; 01189 01190 return(err); 01191 } 01192 } 01193 01194 if (rec_get_converted_size(index, entry) >= 01195 ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2, 01196 REC_MAX_DATA_SIZE)) { 01197 01198 /* The record is so big that we have to store some fields 01199 externally on separate database pages */ 01200 01201 big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0); 01202 01203 if (big_rec_vec == NULL) { 01204 01205 if (n_extents > 0) { 01206 fil_space_release_free_extents(index->space, 01207 n_reserved); 01208 } 01209 return(DB_TOO_BIG_RECORD); 01210 } 01211 } 01212 01213 if (dict_tree_get_page(index->tree) 01214 == buf_frame_get_page_no(page)) { 01215 01216 /* The page is the root page */ 01217 *rec = btr_root_raise_and_insert(cursor, entry, mtr); 01218 } else { 01219 *rec = btr_page_split_and_insert(cursor, entry, mtr); 01220 } 01221 01222 btr_cur_position(index, page_rec_get_prev(*rec), cursor); 01223 01224 #ifdef BTR_CUR_ADAPT 01225 btr_search_update_hash_on_insert(cursor); 01226 #endif 01227 if (!(flags & BTR_NO_LOCKING_FLAG)) { 01228 01229 lock_update_insert(*rec); 01230 } 01231 01232 err = DB_SUCCESS; 01233 01234 if (n_extents > 0) { 01235 fil_space_release_free_extents(index->space, n_reserved); 01236 } 01237 01238 *big_rec = big_rec_vec; 01239 01240 return(err); 01241 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint btr_cur_pessimistic_update | ( | ulint | flags, | |
| btr_cur_t * | cursor, | |||
| big_rec_t ** | big_rec, | |||
| upd_t * | update, | |||
| ulint | cmpl_info, | |||
| que_thr_t * | thr, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 1772 of file btr0cur.c.
References btr_cur_compress_if_useful(), btr_cur_get_page(), btr_cur_get_page_cur(), btr_cur_get_rec(), btr_cur_insert_if_possible(), btr_cur_optimistic_update(), btr_cur_pess_upd_restore_supremum(), btr_cur_pessimistic_insert(), btr_cur_unmark_extern_fields(), btr_cur_upd_lock_and_undo(), BTR_KEEP_SYS_FLAG, BTR_NO_LOCKING_FLAG, BTR_NO_UNDO_LOG_FLAG, btr_push_update_extern_fields(), btr_rec_free_updated_extern_fields(), btr_search_update_hash_on_delete(), buf_block_align(), buf_frame_align(), DATA_ROLL_PTR, DATA_TRX_ID, DB_OUT_OF_FILE_SPACE, DB_OVERFLOW, DB_SUCCESS, DB_TOO_BIG_RECORD, DB_UNDERFLOW, dict_index_get_n_fields(), dict_tree_get_lock(), dtuple_convert_big_rec(), err, FALSE, fil_space_release_free_extents(), FSP_CLEANING, FSP_NORMAL, fsp_reserve_free_extents(), trx_struct::id, btr_cur_struct::index, index(), lock_rec_restore_from_page_infimum(), lock_rec_store_on_page_infimum(), mem_heap_alloc(), mem_heap_create, mem_heap_free, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, MTR_MEMO_X_LOCK, NULL, page, page_cur_delete_rec(), page_cur_is_before_first(), page_cur_move_to_prev(), page_get_free_space_of_empty(), page_is_comp(), page_t, rec_get_converted_size(), rec_get_deleted_flag(), rec_get_node_ptr_flag(), rec_get_offsets, REC_MAX_DATA_SIZE, rec_offs_comp(), rec_set_field_extern_bits(), ROW_COPY_DATA, row_rec_to_index_entry(), row_upd_index_entry_sys_field(), row_upd_index_replace_new_col_vals_index_pos(), thr_get_trx(), btr_cur_struct::tree_height, TRUE, update, ut_a, ut_ad, and ut_min().
Referenced by row_ins_clust_index_entry_by_modify(), row_ins_sec_index_entry_by_modify(), row_undo_mod_clust_low(), row_undo_mod_del_unmark_sec_and_undo_update(), and row_upd_clust_rec().
01774 : DB_SUCCESS or error code */ 01775 ulint flags, /* in: undo logging, locking, and rollback 01776 flags */ 01777 btr_cur_t* cursor, /* in: cursor on the record to update */ 01778 big_rec_t** big_rec,/* out: big rec vector whose fields have to 01779 be stored externally by the caller, or NULL */ 01780 upd_t* update, /* in: update vector; this is allowed also 01781 contain trx id and roll ptr fields, but 01782 the values in update vector have no effect */ 01783 ulint cmpl_info,/* in: compiler info on secondary index 01784 updates */ 01785 que_thr_t* thr, /* in: query thread */ 01786 mtr_t* mtr) /* in: mtr */ 01787 { 01788 big_rec_t* big_rec_vec = NULL; 01789 big_rec_t* dummy_big_rec; 01790 dict_index_t* index; 01791 page_t* page; 01792 dict_tree_t* tree; 01793 rec_t* rec; 01794 page_cur_t* page_cursor; 01795 dtuple_t* new_entry; 01796 mem_heap_t* heap; 01797 ulint err; 01798 ulint optim_err; 01799 ibool dummy_reorganized; 01800 dulint roll_ptr; 01801 trx_t* trx; 01802 ibool was_first; 01803 ibool success; 01804 ulint n_extents = 0; 01805 ulint n_reserved; 01806 ulint* ext_vect; 01807 ulint n_ext_vect; 01808 ulint reserve_flag; 01809 ulint* offsets = NULL; 01810 01811 *big_rec = NULL; 01812 01813 page = btr_cur_get_page(cursor); 01814 rec = btr_cur_get_rec(cursor); 01815 index = cursor->index; 01816 tree = index->tree; 01817 01818 ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), 01819 MTR_MEMO_X_LOCK)); 01820 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 01821 MTR_MEMO_PAGE_X_FIX)); 01822 01823 optim_err = btr_cur_optimistic_update(flags, cursor, update, 01824 cmpl_info, thr, mtr); 01825 01826 if (optim_err != DB_UNDERFLOW && optim_err != DB_OVERFLOW) { 01827 01828 return(optim_err); 01829 } 01830 01831 /* Do lock checking and undo logging */ 01832 err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info, 01833 thr, &roll_ptr); 01834 if (err != DB_SUCCESS) { 01835 01836 return(err); 01837 } 01838 01839 if (optim_err == DB_OVERFLOW) { 01840 /* First reserve enough free space for the file segments 01841 of the index tree, so that the update will not fail because 01842 of lack of space */ 01843 01844 n_extents = cursor->tree_height / 16 + 3; 01845 01846 if (flags & BTR_NO_UNDO_LOG_FLAG) { 01847 reserve_flag = FSP_CLEANING; 01848 } else { 01849 reserve_flag = FSP_NORMAL; 01850 } 01851 01852 success = fsp_reserve_free_extents(&n_reserved, 01853 index->space, 01854 n_extents, reserve_flag, mtr); 01855 if (!success) { 01856 err = DB_OUT_OF_FILE_SPACE; 01857 01858 return(err); 01859 } 01860 } 01861 01862 heap = mem_heap_create(1024); 01863 offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); 01864 01865 trx = thr_get_trx(thr); 01866 01867 new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); 01868 01869 row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, 01870 FALSE, heap); 01871 if (!(flags & BTR_KEEP_SYS_FLAG)) { 01872 row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR, 01873 roll_ptr); 01874 row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID, 01875 trx->id); 01876 } 01877 01878 if (flags & BTR_NO_UNDO_LOG_FLAG) { 01879 /* We are in a transaction rollback undoing a row 01880 update: we must free possible externally stored fields 01881 which got new values in the update, if they are not 01882 inherited values. They can be inherited if we have 01883 updated the primary key to another value, and then 01884 update it back again. */ 01885 01886 ut_a(big_rec_vec == NULL); 01887 01888 btr_rec_free_updated_extern_fields(index, rec, offsets, 01889 update, TRUE, mtr); 01890 } 01891 01892 /* We have to set appropriate extern storage bits in the new 01893 record to be inserted: we have to remember which fields were such */ 01894 01895 ext_vect = mem_heap_alloc(heap, sizeof(ulint) 01896 * dict_index_get_n_fields(index)); 01897 ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec)); 01898 offsets = rec_get_offsets(rec, index, offsets, 01899 ULINT_UNDEFINED, &heap); 01900 n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, update); 01901 01902 if (UNIV_UNLIKELY(rec_get_converted_size(index, new_entry) >= 01903 ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2, 01904 REC_MAX_DATA_SIZE))) { 01905 01906 big_rec_vec = dtuple_convert_big_rec(index, new_entry, 01907 ext_vect, n_ext_vect); 01908 if (big_rec_vec == NULL) { 01909 01910 err = DB_TOO_BIG_RECORD; 01911 goto return_after_reservations; 01912 } 01913 } 01914 01915 page_cursor = btr_cur_get_page_cur(cursor); 01916 01917 /* Store state of explicit locks on rec on the page infimum record, 01918 before deleting rec. The page infimum acts as a dummy carrier of the 01919 locks, taking care also of lock releases, before we can move the locks 01920 back on the actual record. There is a special case: if we are 01921 inserting on the root page and the insert causes a call of 01922 btr_root_raise_and_insert. Therefore we cannot in the lock system 01923 delete the lock structs set on the root page even if the root 01924 page carries just node pointers. */ 01925 01926 lock_rec_store_on_page_infimum(buf_frame_align(rec), rec); 01927 01928 btr_search_update_hash_on_delete(cursor); 01929 01930 page_cur_delete_rec(page_cursor, index, offsets, mtr); 01931 01932 page_cur_move_to_prev(page_cursor); 01933 01934 rec = btr_cur_insert_if_possible(cursor, new_entry, 01935 &dummy_reorganized, mtr); 01936 ut_a(rec || optim_err != DB_UNDERFLOW); 01937 01938 if (rec) { 01939 lock_rec_restore_from_page_infimum(rec, page); 01940 rec_set_field_extern_bits(rec, index, 01941 ext_vect, n_ext_vect, mtr); 01942 01943 offsets = rec_get_offsets(rec, index, offsets, 01944 ULINT_UNDEFINED, &heap); 01945 01946 if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) { 01947 /* The new inserted record owns its possible externally 01948 stored fields */ 01949 btr_cur_unmark_extern_fields(rec, mtr, offsets); 01950 } 01951 01952 btr_cur_compress_if_useful(cursor, mtr); 01953 01954 err = DB_SUCCESS; 01955 goto return_after_reservations; 01956 } 01957 01958 if (page_cur_is_before_first(page_cursor)) { 01959 /* The record to be updated was positioned as the first user 01960 record on its page */ 01961 01962 was_first = TRUE; 01963 } else { 01964 was_first = FALSE; 01965 } 01966 01967 /* The first parameter means that no lock checking and undo logging 01968 is made in the insert */ 01969 01970 err = btr_cur_pessimistic_insert(BTR_NO_UNDO_LOG_FLAG 01971 | BTR_NO_LOCKING_FLAG 01972 | BTR_KEEP_SYS_FLAG, 01973 cursor, new_entry, &rec, 01974 &dummy_big_rec, NULL, mtr); 01975 ut_a(rec); 01976 ut_a(err == DB_SUCCESS); 01977 ut_a(dummy_big_rec == NULL); 01978 01979 rec_set_field_extern_bits(rec, index, ext_vect, n_ext_vect, mtr); 01980 offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); 01981 01982 if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) { 01983 /* The new inserted record owns its possible externally 01984 stored fields */ 01985 01986 btr_cur_unmark_extern_fields(rec, mtr, offsets); 01987 } 01988 01989 lock_rec_restore_from_page_infimum(rec, page); 01990 01991 /* If necessary, restore also the correct lock state for a new, 01992 preceding supremum record created in a page split. While the old 01993 record was nonexistent, the supremum might have inherited its locks 01994 from a wrong record. */ 01995 01996 if (!was_first) { 01997 btr_cur_pess_upd_restore_supremum(rec, mtr); 01998 } 01999 02000 return_after_reservations: 02001 mem_heap_free(heap); 02002 02003 if (n_extents > 0) { 02004 fil_space_release_free_extents(index->space, n_reserved); 02005 } 02006 02007 *big_rec = big_rec_vec; 02008 02009 return(err); 02010 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void btr_cur_position | ( | dict_index_t * | index, | |
| rec_t * | rec, | |||
| btr_cur_t * | cursor | |||
| ) |
Referenced by btr_cur_pessimistic_insert(), btr_node_ptr_delete(), btr_search_guess_on_hash(), and row_ins_index_entry_low().
Here is the caller graph for this function:

| void btr_cur_search_to_nth_level | ( | dict_index_t * | index, | |
| ulint | level, | |||
| dtuple_t * | tuple, | |||
| ulint | mode, | |||
| ulint | latch_mode, | |||
| btr_cur_t * | cursor, | |||
| ulint | has_search_latch, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 243 of file btr0cur.c.
References BTR_CONT_MODIFY_TREE, btr_cur_add_path_info(), BTR_CUR_BINARY, btr_cur_get_page_cur(), BTR_CUR_INSERT_TO_IBUF, btr_cur_latch_leaves(), btr_cur_n_non_sea, btr_cur_n_sea, BTR_ESTIMATE, BTR_IGNORE_SEC_UNIQUE, BTR_INSERT, BTR_MODIFY_LEAF, BTR_MODIFY_TREE, btr_node_ptr_get_child_page_no(), btr_page_get(), btr_page_get_index_id(), btr_page_get_level(), btr_search_get_info(), btr_search_guess_on_hash(), btr_search_info_update(), btr_search_latch, buf_block_align(), BUF_GET, BUF_GET_IF_IN_POOL, buf_page_get_gen(), buf_block_struct::check_index_page_at_flush, DICT_IBUF, dict_table_is_comp(), dict_tree_get_lock(), dict_tree_get_page(), dict_tree_get_space(), dtuple_check_typed(), btr_cur_struct::flag, ibuf_insert(), ibuf_inside(), ibuf_should_try(), dict_tree_struct::id, btr_cur_struct::index, index(), info, btr_cur_struct::low_bytes, btr_cur_struct::low_match, mem_heap_free, mtr_memo_contains(), MTR_MEMO_X_LOCK, mtr_release_s_latch_at_savepoint(), mtr_s_lock, mtr_set_savepoint(), mtr_x_lock, NULL, page, PAGE_CUR_G, PAGE_CUR_GE, page_cur_get_page(), page_cur_get_rec(), PAGE_CUR_L, PAGE_CUR_LE, page_cur_search_with_match(), page_is_comp(), page_t, rec_get_offsets, REC_OFFS_NORMAL_SIZE, btr_search_struct::root_guess, RW_LOCK_NOT_LOCKED, rw_lock_s_lock, rw_lock_s_unlock, RW_NO_LATCH, RW_X_LATCH, srv_use_adaptive_hash_indexes, SYNC_TREE_NODE, btr_cur_struct::thr, btr_cur_struct::tree_height, TRUE, btr_cur_struct::up_bytes, btr_cur_struct::up_match, ut_a, ut_ad, and ut_dulint_cmp().
Referenced by btr_estimate_n_rows_in_range(), btr_insert_on_non_leaf_level(), btr_page_get_father_for_rec(), btr_search_guess_on_hash(), and row_ins_index_entry_low().
00245 : index */ 00246 ulint level, /* in: the tree level of search */ 00247 dtuple_t* tuple, /* in: data tuple; NOTE: n_fields_cmp in 00248 tuple must be set so that it cannot get 00249 compared to the node ptr page number field! */ 00250 ulint mode, /* in: PAGE_CUR_L, ...; 00251 Inserts should always be made using 00252 PAGE_CUR_LE to search the position! */ 00253 ulint latch_mode, /* in: BTR_SEARCH_LEAF, ..., ORed with 00254 BTR_INSERT and BTR_ESTIMATE; 00255 cursor->left_page is used to store a pointer 00256 to the left neighbor page, in the cases 00257 BTR_SEARCH_PREV and BTR_MODIFY_PREV; 00258 NOTE that if has_search_latch 00259 is != 0, we maybe do not have a latch set 00260 on the cursor page, we assume 00261 the caller uses his search latch 00262 to protect the record! */ 00263 btr_cur_t* cursor, /* in/out: tree cursor; the cursor page is 00264 s- or x-latched, but see also above! */ 00265 ulint has_search_latch,/* in: info on the latch mode the 00266 caller currently has on btr_search_latch: 00267 RW_S_LATCH, or 0 */ 00268 mtr_t* mtr) /* in: mtr */ 00269 { 00270 dict_tree_t* tree; 00271 page_cur_t* page_cursor; 00272 page_t* page; 00273 page_t* guess; 00274 rec_t* node_ptr; 00275 ulint page_no; 00276 ulint space; 00277 ulint up_match; 00278 ulint up_bytes; 00279 ulint low_match; 00280 ulint low_bytes; 00281 ulint height; 00282 ulint savepoint; 00283 ulint rw_latch; 00284 ulint page_mode; 00285 ulint insert_planned; 00286 ulint buf_mode; 00287 ulint estimate; 00288 ulint ignore_sec_unique; 00289 ulint root_height = 0; /* remove warning */ 00290 #ifdef BTR_CUR_ADAPT 00291 btr_search_t* info; 00292 #endif 00293 mem_heap_t* heap = NULL; 00294 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 00295 ulint* offsets = offsets_; 00296 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 00297 /* Currently, PAGE_CUR_LE is the only search mode used for searches 00298 ending to upper levels */ 00299 00300 ut_ad(level == 0 || mode == PAGE_CUR_LE); 00301 ut_ad(dict_tree_check_search_tuple(index->tree, tuple)); 00302 ut_ad(!(index->type & DICT_IBUF) || ibuf_inside()); 00303 ut_ad(dtuple_check_typed(tuple)); 00304 00305 #ifdef UNIV_DEBUG 00306 cursor->up_match = ULINT_UNDEFINED; 00307 cursor->low_match = ULINT_UNDEFINED; 00308 #endif 00309 insert_planned = latch_mode & BTR_INSERT; 00310 estimate = latch_mode & BTR_ESTIMATE; 00311 ignore_sec_unique = latch_mode & BTR_IGNORE_SEC_UNIQUE; 00312 latch_mode = latch_mode & ~(BTR_INSERT | BTR_ESTIMATE 00313 | BTR_IGNORE_SEC_UNIQUE); 00314 00315 ut_ad(!insert_planned || (mode == PAGE_CUR_LE)); 00316 00317 cursor->flag = BTR_CUR_BINARY; 00318 cursor->index = index; 00319 00320 #ifndef BTR_CUR_ADAPT 00321 guess = NULL; 00322 #else 00323 info = btr_search_get_info(index); 00324 00325 guess = info->root_guess; 00326 00327 #ifdef BTR_CUR_HASH_ADAPT 00328 00329 #ifdef UNIV_SEARCH_PERF_STAT 00330 info->n_searches++; 00331 #endif 00332 if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED 00333 && latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ 00334 && !estimate 00335 #ifdef PAGE_CUR_LE_OR_EXTENDS 00336 && mode != PAGE_CUR_LE_OR_EXTENDS 00337 #endif /* PAGE_CUR_LE_OR_EXTENDS */ 00338 && srv_use_adaptive_hash_indexes 00339 && btr_search_guess_on_hash(index, info, tuple, mode, 00340 latch_mode, cursor, 00341 has_search_latch, mtr)) { 00342 00343 /* Search using the hash index succeeded */ 00344 00345 ut_ad(cursor->up_match != ULINT_UNDEFINED 00346 || mode != PAGE_CUR_GE); 00347 ut_ad(cursor->up_match != ULINT_UNDEFINED 00348 || mode != PAGE_CUR_LE); 00349 ut_ad(cursor->low_match != ULINT_UNDEFINED 00350 || mode != PAGE_CUR_LE); 00351 btr_cur_n_sea++; 00352 00353 return; 00354 } 00355 #endif 00356 #endif 00357 btr_cur_n_non_sea++; 00358 00359 /* If the hash search did not succeed, do binary search down the 00360 tree */ 00361 00362 if (has_search_latch) { 00363 /* Release possible search latch to obey latching order */ 00364 rw_lock_s_unlock(&btr_search_latch); 00365 } 00366 00367 /* Store the position of the tree latch we push to mtr so that we 00368 know how to release it when we have latched leaf node(s) */ 00369 00370 savepoint = mtr_set_savepoint(mtr); 00371 00372 tree = index->tree; 00373 00374 if (latch_mode == BTR_MODIFY_TREE) { 00375 mtr_x_lock(dict_tree_get_lock(tree), mtr); 00376 00377 } else if (latch_mode == BTR_CONT_MODIFY_TREE) { 00378 /* Do nothing */ 00379 ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), 00380 MTR_MEMO_X_LOCK)); 00381 } else { 00382 mtr_s_lock(dict_tree_get_lock(tree), mtr); 00383 } 00384 00385 page_cursor = btr_cur_get_page_cur(cursor); 00386 00387 space = dict_tree_get_space(tree); 00388 page_no = dict_tree_get_page(tree); 00389 00390 up_match = 0; 00391 up_bytes = 0; 00392 low_match = 0; 00393 low_bytes = 0; 00394 00395 height = ULINT_UNDEFINED; 00396 rw_latch = RW_NO_LATCH; 00397 buf_mode = BUF_GET; 00398 00399 /* We use these modified search modes on non-leaf levels of the 00400 B-tree. These let us end up in the right B-tree leaf. In that leaf 00401 we use the original search mode. */ 00402 00403 switch (mode) { 00404 case PAGE_CUR_GE: 00405 page_mode = PAGE_CUR_L; 00406 break; 00407 case PAGE_CUR_G: 00408 page_mode = PAGE_CUR_LE; 00409 break; 00410 default: 00411 #ifdef PAGE_CUR_LE_OR_EXTENDS 00412 ut_ad(mode == PAGE_CUR_L || mode == PAGE_CUR_LE 00413 || mode == PAGE_CUR_LE_OR_EXTENDS); 00414 #else /* PAGE_CUR_LE_OR_EXTENDS */ 00415 ut_ad(mode == PAGE_CUR_L || mode == PAGE_CUR_LE); 00416 #endif /* PAGE_CUR_LE_OR_EXTENDS */ 00417 page_mode = mode; 00418 break; 00419 } 00420 00421 /* Loop and search until we arrive at the desired level */ 00422 00423 for (;;) { 00424 if ((height == 0) && (latch_mode <= BTR_MODIFY_LEAF)) { 00425 00426 rw_latch = latch_mode; 00427 00428 if (insert_planned && ibuf_should_try(index, 00429 ignore_sec_unique)) { 00430 00431 /* Try insert to the insert buffer if the 00432 page is not in the buffer pool */ 00433 00434 buf_mode = BUF_GET_IF_IN_POOL; 00435 } 00436 } 00437 retry_page_get: 00438 page = buf_page_get_gen(space, page_no, rw_latch, guess, 00439 buf_mode, 00440 __FILE__, __LINE__, 00441 mtr); 00442 if (page == NULL) { 00443 /* This must be a search to perform an insert; 00444 try insert to the insert buffer */ 00445 00446 ut_ad(buf_mode == BUF_GET_IF_IN_POOL); 00447 ut_ad(insert_planned); 00448 ut_ad(cursor->thr); 00449 00450 if (ibuf_should_try(index, ignore_sec_unique) && 00451 ibuf_insert(tuple, index, space, page_no, 00452 cursor->thr)) { 00453 /* Insertion to the insert buffer succeeded */ 00454 cursor->flag = BTR_CUR_INSERT_TO_IBUF; 00455 if (UNIV_LIKELY_NULL(heap)) { 00456 mem_heap_free(heap); 00457 } 00458 goto func_exit; 00459 } 00460 00461 /* Insert to the insert buffer did not succeed: 00462 retry page get */ 00463 00464 buf_mode = BUF_GET; 00465 00466 goto retry_page_get; 00467 } 00468 00469 buf_block_align(page)->check_index_page_at_flush = TRUE; 00470 00471 #ifdef UNIV_SYNC_DEBUG 00472 if (rw_latch != RW_NO_LATCH) { 00473 buf_page_dbg_add_level(page, SYNC_TREE_NODE); 00474 } 00475 #endif 00476 ut_ad(0 == ut_dulint_cmp(tree->id, 00477 btr_page_get_index_id(page))); 00478 00479 if (height == ULINT_UNDEFINED) { 00480 /* We are in the root node */ 00481 00482 height = btr_page_get_level(page, mtr); 00483 root_height = height; 00484 cursor->tree_height = root_height + 1; 00485 #ifdef BTR_CUR_ADAPT 00486 if (page != guess) { 00487 info->root_guess = page; 00488 } 00489 #endif 00490 } 00491 00492 if (height == 0) { 00493 if (rw_latch == RW_NO_LATCH) { 00494 00495 btr_cur_latch_leaves(page, space, 00496 page_no, latch_mode, cursor, 00497 mtr); 00498 } 00499 00500 if ((latch_mode != BTR_MODIFY_TREE) 00501 && (latch_mode != BTR_CONT_MODIFY_TREE)) { 00502 00503 /* Release the tree s-latch */ 00504 00505 mtr_release_s_latch_at_savepoint( 00506 mtr, savepoint, 00507 dict_tree_get_lock(tree)); 00508 } 00509 00510 page_mode = mode; 00511 } 00512 00513 page_cur_search_with_match(page, index, tuple, page_mode, 00514 &up_match, &up_bytes, 00515 &low_match, &low_bytes, page_cursor); 00516 if (estimate) { 00517 btr_cur_add_path_info(cursor, height, root_height); 00518 } 00519 00520 /* If this is the desired level, leave the loop */ 00521 00522 ut_ad(height 00523 == btr_page_get_level(page_cur_get_page(page_cursor), mtr)); 00524 00525 if (level == height) { 00526 00527 if (level > 0) { 00528 /* x-latch the page */ 00529 page = btr_page_get(space, 00530 page_no, RW_X_LATCH, mtr); 00531 ut_a((ibool)!!page_is_comp(page) 00532 == dict_table_is_comp(index->table)); 00533 } 00534 00535 break; 00536 } 00537 00538 ut_ad(height > 0); 00539 00540 height--; 00541 guess = NULL; 00542 00543 node_ptr = page_cur_get_rec(page_cursor); 00544 offsets = rec_get_offsets(node_ptr, cursor->index, offsets, 00545 ULINT_UNDEFINED, &heap); 00546 /* Go to the child node */ 00547 page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); 00548 } 00549 00550 if (UNIV_LIKELY_NULL(heap)) { 00551 mem_heap_free(heap); 00552 } 00553 00554 if (level == 0) { 00555 cursor->low_match = low_match; 00556 cursor->low_bytes = low_bytes; 00557 cursor->up_match = up_match; 00558 cursor->up_bytes = up_bytes; 00559 00560 #ifdef BTR_CUR_ADAPT 00561 if (srv_use_adaptive_hash_indexes) { 00562 00563 btr_search_info_update(index, cursor); 00564 } 00565 #endif 00566 ut_ad(cursor->up_match != ULINT_UNDEFINED 00567 || mode != PAGE_CUR_GE); 00568 ut_ad(cursor->up_match != ULINT_UNDEFINED 00569 || mode != PAGE_CUR_LE); 00570 ut_ad(cursor->low_match != ULINT_UNDEFINED 00571 || mode != PAGE_CUR_LE); 00572 } 00573 00574 func_exit: 00575 if (has_search_latch) { 00576 00577 rw_lock_s_lock(&btr_search_latch); 00578 } 00579 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3221 of file btr0cur.c.
References BTR_EXTERN_FIELD_REF_SIZE, BTR_EXTERN_LEN, BTR_EXTERN_OWNER_FLAG, data, dfield_get_data(), dfield_get_len(), dtuple_get_nth_field(), mach_read_from_1(), and mach_write_to_1().
Referenced by row_upd_clust_rec_by_insert().
03223 : clustered index entry */ 03224 ulint* ext_vec, /* in: array of numbers of fields 03225 which have been stored externally */ 03226 ulint n_ext_vec) /* in: number of elements in ext_vec */ 03227 { 03228 dfield_t* dfield; 03229 ulint byte_val; 03230 byte* data; 03231 ulint len; 03232 ulint i; 03233 03234 for (i = 0; i < n_ext_vec; i++) { 03235 dfield = dtuple_get_nth_field(entry, ext_vec[i]); 03236 03237 data = (byte*) dfield_get_data(dfield); 03238 len = dfield_get_len(dfield); 03239 03240 len -= BTR_EXTERN_FIELD_REF_SIZE; 03241 03242 byte_val = mach_read_from_1(data + len + BTR_EXTERN_LEN); 03243 03244 byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG); 03245 03246 mach_write_to_1(data + len + BTR_EXTERN_LEN, byte_val); 03247 } 03248 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint btr_cur_update_in_place | ( | ulint | flags, | |
| btr_cur_t * | cursor, | |||
| upd_t * | update, | |||
| ulint | cmpl_info, | |||
| que_thr_t * | thr, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 1436 of file btr0cur.c.
References yaSSL::block, btr_cur_get_rec(), btr_cur_unmark_extern_fields(), btr_cur_upd_lock_and_undo(), btr_cur_update_in_place_log(), BTR_KEEP_SYS_FLAG, btr_search_latch, btr_search_update_hash_on_delete(), buf_block_align(), buf_block_get_frame(), DB_SUCCESS, DICT_CLUSTERED, dict_table_is_comp(), err, btr_cur_struct::index, index(), mem_heap_free, NULL, page_is_comp(), page_rec_is_comp(), rec_get_deleted_flag(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, rec_print_new(), row_upd_changes_ord_field_binary(), row_upd_rec_in_place(), row_upd_rec_sys_fields(), rw_lock_x_lock, rw_lock_x_unlock, thr_get_trx(), update, ut_ad, and ut_dulint_zero.
Referenced by btr_cur_optimistic_update(), row_upd_clust_rec(), and row_upd_in_place_in_select().
01438 : DB_SUCCESS or error number */ 01439 ulint flags, /* in: undo logging and locking flags */ 01440 btr_cur_t* cursor, /* in: cursor on the record to update; 01441 cursor stays valid and positioned on the 01442 same record */ 01443 upd_t* update, /* in: update vector */ 01444 ulint cmpl_info,/* in: compiler info on secondary index 01445 updates */ 01446 que_thr_t* thr, /* in: query thread */ 01447 mtr_t* mtr) /* in: mtr */ 01448 { 01449 dict_index_t* index; 01450 buf_block_t* block; 01451 ulint err; 01452 rec_t* rec; 01453 dulint roll_ptr = ut_dulint_zero; 01454 trx_t* trx; 01455 ulint was_delete_marked; 01456 mem_heap_t* heap = NULL; 01457 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01458 ulint* offsets = offsets_; 01459 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01460 01461 rec = btr_cur_get_rec(cursor); 01462 index = cursor->index; 01463 ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); 01464 trx = thr_get_trx(thr); 01465 offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); 01466 #ifdef UNIV_DEBUG 01467 if (btr_cur_print_record_ops && thr) { 01468 btr_cur_trx_report(trx, index, "update "); 01469 rec_print_new(stderr, rec, offsets); 01470 } 01471 #endif /* UNIV_DEBUG */ 01472 01473 /* Do lock checking and undo logging */ 01474 err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info, 01475 thr, &roll_ptr); 01476 if (UNIV_UNLIKELY(err != DB_SUCCESS)) { 01477 01478 if (UNIV_LIKELY_NULL(heap)) { 01479 mem_heap_free(heap); 01480 } 01481 return(err); 01482 } 01483 01484 block = buf_block_align(rec); 01485 ut_ad(!!page_is_comp(buf_block_get_frame(block)) 01486 == dict_table_is_comp(index->table)); 01487 01488 if (block->is_hashed) { 01489 /* The function row_upd_changes_ord_field_binary works only 01490 if the update vector was built for a clustered index, we must 01491 NOT call it if index is secondary */ 01492 01493 if (!(index->type & DICT_CLUSTERED) 01494 || row_upd_changes_ord_field_binary(NULL, index, update)) { 01495 01496 /* Remove possible hash index pointer to this record */ 01497 btr_search_update_hash_on_delete(cursor); 01498 } 01499 01500 rw_lock_x_lock(&btr_search_latch); 01501 } 01502 01503 if (!(flags & BTR_KEEP_SYS_FLAG)) { 01504 row_upd_rec_sys_fields(rec, index, offsets, trx, roll_ptr); 01505 } 01506 01507 /* FIXME: in a mixed tree, all records may not have enough ordering 01508 fields for btr search: */ 01509 01510 was_delete_marked = rec_get_deleted_flag(rec, 01511 page_is_comp(buf_block_get_frame(block))); 01512 01513 row_upd_rec_in_place(rec, offsets, update); 01514 01515 if (block->is_hashed) { 01516 rw_lock_x_unlock(&btr_search_latch); 01517 } 01518 01519 btr_cur_update_in_place_log(flags, rec, index, update, trx, roll_ptr, 01520 mtr); 01521 if (was_delete_marked && !rec_get_deleted_flag(rec, 01522 page_is_comp(buf_block_get_frame(block)))) { 01523 /* The new updated record owns its possible externally 01524 stored fields */ 01525 01526 btr_cur_unmark_extern_fields(rec, mtr, offsets); 01527 } 01528 01529 if (UNIV_LIKELY_NULL(heap)) { 01530 mem_heap_free(heap); 01531 } 01532 return(DB_SUCCESS); 01533 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ib_longlong btr_estimate_n_rows_in_range | ( | dict_index_t * | index, | |
| dtuple_t * | tuple1, | |||
| ulint | mode1, | |||
| dtuple_t * | tuple2, | |||
| ulint | mode2 | |||
| ) |
Definition at line 2695 of file btr0cur.c.
References btr_cur_open_at_index_side(), btr_cur_search_to_nth_level(), BTR_ESTIMATE, BTR_PATH_ARRAY_N_SLOTS, BTR_SEARCH_LEAF, dtuple_get_n_fields(), FALSE, index(), mtr_commit(), mtr_start(), btr_path_struct::nth_rec, btr_cur_struct::path_arr, TRUE, and ut_ad.
02697 : estimated number of rows */ 02698 dict_index_t* index, /* in: index */ 02699 dtuple_t* tuple1, /* in: range start, may also be empty tuple */ 02700 ulint mode1, /* in: search mode for range start */ 02701 dtuple_t* tuple2, /* in: range end, may also be empty tuple */ 02702 ulint mode2) /* in: search mode for range end */ 02703 { 02704 btr_path_t path1[BTR_PATH_ARRAY_N_SLOTS]; 02705 btr_path_t path2[BTR_PATH_ARRAY_N_SLOTS]; 02706 btr_cur_t cursor; 02707 btr_path_t* slot1; 02708 btr_path_t* slot2; 02709 ibool diverged; 02710 ibool diverged_lot; 02711 ulint divergence_level; 02712 ib_longlong n_rows; 02713 ulint i; 02714 mtr_t mtr; 02715 02716 mtr_start(&mtr); 02717 02718 cursor.path_arr = path1; 02719 02720 if (dtuple_get_n_fields(tuple1) > 0) { 02721 02722 btr_cur_search_to_nth_level(index, 0, tuple1, mode1, 02723 BTR_SEARCH_LEAF | BTR_ESTIMATE, 02724 &cursor, 0, &mtr); 02725 } else { 02726 btr_cur_open_at_index_side(TRUE, index, 02727 BTR_SEARCH_LEAF | BTR_ESTIMATE, 02728 &cursor, &mtr); 02729 } 02730 02731 mtr_commit(&mtr); 02732 02733 mtr_start(&mtr); 02734 02735 cursor.path_arr = path2; 02736 02737 if (dtuple_get_n_fields(tuple2) > 0) { 02738 02739 btr_cur_search_to_nth_level(index, 0, tuple2, mode2, 02740 BTR_SEARCH_LEAF | BTR_ESTIMATE, 02741 &cursor, 0, &mtr); 02742 } else { 02743 btr_cur_open_at_index_side(FALSE, index, 02744 BTR_SEARCH_LEAF | BTR_ESTIMATE, 02745 &cursor, &mtr); 02746 } 02747 02748 mtr_commit(&mtr); 02749 02750 /* We have the path information for the range in path1 and path2 */ 02751 02752 n_rows = 1; 02753 diverged = FALSE; /* This becomes true when the path is not 02754 the same any more */ 02755 diverged_lot = FALSE; /* This becomes true when the paths are 02756 not the same or adjacent any more */ 02757 divergence_level = 1000000; /* This is the level where paths diverged 02758 a lot */ 02759 for (i = 0; ; i++) { 02760 ut_ad(i < BTR_PATH_ARRAY_N_SLOTS); 02761 02762 slot1 = path1 + i; 02763 slot2 = path2 + i; 02764 02765 if (slot1->nth_rec == ULINT_UNDEFINED 02766 || slot2->nth_rec == ULINT_UNDEFINED) { 02767 02768 if (i > divergence_level + 1) { 02769 /* In trees whose height is > 1 our algorithm 02770 tends to underestimate: multiply the estimate 02771 by 2: */ 02772 02773 n_rows = n_rows * 2; 02774 } 02775 02776 /* Do not estimate the number of rows in the range 02777 to over 1 / 2 of the estimated rows in the whole 02778 table */ 02779 02780 if (n_rows > index->table->stat_n_rows / 2) { 02781 n_rows = index->table->stat_n_rows / 2; 02782 02783 /* If there are just 0 or 1 rows in the table, 02784 then we estimate all rows are in the range */ 02785 02786 if (n_rows == 0) { 02787 n_rows = index->table->stat_n_rows; 02788 } 02789 } 02790 02791 return(n_rows); 02792 } 02793 02794 if (!diverged && slot1->nth_rec != slot2->nth_rec) { 02795 02796 diverged = TRUE; 02797 02798 if (slot1->nth_rec < slot2->nth_rec) { 02799 n_rows = slot2->nth_rec - slot1->nth_rec; 02800 02801 if (n_rows > 1) { 02802 diverged_lot = TRUE; 02803 divergence_level = i; 02804 } 02805 } else { 02806 /* Maybe the tree has changed between 02807 searches */ 02808 02809 return(10); 02810 } 02811 02812 } else if (diverged && !diverged_lot) { 02813 02814 if (slot1->nth_rec < slot1->n_recs 02815 || slot2->nth_rec > 1) { 02816 02817 diverged_lot = TRUE; 02818 divergence_level = i; 02819 02820 n_rows = 0; 02821 02822 if (slot1->nth_rec < slot1->n_recs) { 02823 n_rows += slot1->n_recs 02824 - slot1->nth_rec; 02825 } 02826 02827 if (slot2->nth_rec > 1) { 02828 n_rows += slot2->nth_rec - 1; 02829 } 02830 } 02831 } else if (diverged_lot) { 02832 02833 n_rows = (n_rows * (slot1->n_recs + slot2->n_recs)) 02834 / 2; 02835 } 02836 } 02837 }
Here is the call graph for this function:

| void btr_estimate_number_of_different_key_vals | ( | dict_index_t * | index | ) |
Definition at line 2845 of file btr0cur.c.
References btr_cur_get_page(), btr_cur_open_at_rnd_pos(), BTR_KEY_VAL_ESTIMATE_N_PAGES, btr_page_get_next(), btr_page_get_prev(), btr_rec_get_externally_stored_len(), BTR_SEARCH_LEAF, cmp_rec_rec_with_match(), dict_index_get_n_unique(), dict_index_get_n_unique_in_tree(), FIL_NULL, index(), mem_alloc, mem_free, mem_heap_free, memset, mtr_commit(), mtr_start(), NULL, page, page_get_infimum_rec(), page_get_supremum_rec(), page_rec_get_next(), page_t, rec_get_offsets, and REC_OFFS_NORMAL_SIZE.
Referenced by dict_update_statistics_low().
02847 : index */ 02848 { 02849 btr_cur_t cursor; 02850 page_t* page; 02851 rec_t* rec; 02852 ulint n_cols; 02853 ulint matched_fields; 02854 ulint matched_bytes; 02855 ib_longlong* n_diff; 02856 ulint not_empty_flag = 0; 02857 ulint total_external_size = 0; 02858 ulint i; 02859 ulint j; 02860 ulint add_on; 02861 mtr_t mtr; 02862 mem_heap_t* heap = NULL; 02863 ulint offsets_rec_[REC_OFFS_NORMAL_SIZE]; 02864 ulint offsets_next_rec_[REC_OFFS_NORMAL_SIZE]; 02865 ulint* offsets_rec = offsets_rec_; 02866 ulint* offsets_next_rec= offsets_next_rec_; 02867 *offsets_rec_ = (sizeof offsets_rec_) / sizeof *offsets_rec_; 02868 *offsets_next_rec_ = 02869 (sizeof offsets_next_rec_) / sizeof *offsets_next_rec_; 02870 02871 n_cols = dict_index_get_n_unique(index); 02872 02873 n_diff = mem_alloc((n_cols + 1) * sizeof(ib_longlong)); 02874 02875 memset(n_diff, 0, (n_cols + 1) * sizeof(ib_longlong)); 02876 02877 /* We sample some pages in the index to get an estimate */ 02878 02879 for (i = 0; i < BTR_KEY_VAL_ESTIMATE_N_PAGES; i++) { 02880 rec_t* supremum; 02881 mtr_start(&mtr); 02882 02883 btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr); 02884 02885 /* Count the number of different key values for each prefix of 02886 the key on this index page. If the prefix does not determine 02887 the index record uniquely in te B-tree, then we subtract one 02888 because otherwise our algorithm would give a wrong estimate 02889 for an index where there is just one key value. */ 02890 02891 page = btr_cur_get_page(&cursor); 02892 02893 supremum = page_get_supremum_rec(page); 02894 rec = page_rec_get_next(page_get_infimum_rec(page)); 02895 02896 if (rec != supremum) { 02897 not_empty_flag = 1; 02898 offsets_rec = rec_get_offsets(rec, index, offsets_rec, 02899 ULINT_UNDEFINED, &heap); 02900 } 02901 02902 while (rec != supremum) { 02903 rec_t* next_rec = page_rec_get_next(rec); 02904 if (next_rec == supremum) { 02905 break; 02906 } 02907 02908 matched_fields = 0; 02909 matched_bytes = 0; 02910 offsets_next_rec = rec_get_offsets(next_rec, index, 02911 offsets_next_rec, 02912 n_cols, &heap); 02913 02914 cmp_rec_rec_with_match(rec, next_rec, 02915 offsets_rec, offsets_next_rec, 02916 index, &matched_fields, 02917 &matched_bytes); 02918 02919 for (j = matched_fields + 1; j <= n_cols; j++) { 02920 /* We add one if this index record has 02921 a different prefix from the previous */ 02922 02923 n_diff[j]++; 02924 } 02925 02926 total_external_size += 02927 btr_rec_get_externally_stored_len( 02928 rec, offsets_rec); 02929 02930 rec = next_rec; 02931 /* Initialize offsets_rec for the next round 02932 and assign the old offsets_rec buffer to 02933 offsets_next_rec. */ 02934 { 02935 ulint* offsets_tmp = offsets_rec; 02936 offsets_rec = offsets_next_rec; 02937 offsets_next_rec = offsets_tmp; 02938 } 02939 } 02940 02941 02942 if (n_cols == dict_index_get_n_unique_in_tree(index)) { 02943 02944 /* If there is more than one leaf page in the tree, 02945 we add one because we know that the first record 02946 on the page certainly had a different prefix than the 02947 last record on the previous index page in the 02948 alphabetical order. Before this fix, if there was 02949 just one big record on each clustered index page, the 02950 algorithm grossly underestimated the number of rows 02951 in the table. */ 02952 02953 if (btr_page_get_prev(page, &mtr) != FIL_NULL 02954 || btr_page_get_next(page, &mtr) != FIL_NULL) { 02955 02956 n_diff[n_cols]++; 02957 } 02958 } 02959 02960 offsets_rec = rec_get_offsets(rec, index, offsets_rec, 02961 ULINT_UNDEFINED, &heap); 02962 total_external_size += 02963 btr_rec_get_externally_stored_len(rec, 02964 offsets_rec); 02965 mtr_commit(&mtr); 02966 } 02967 02968 /* If we saw k borders between different key values on 02969 BTR_KEY_VAL_ESTIMATE_N_PAGES leaf pages, we can estimate how many 02970 there will be in index->stat_n_leaf_pages */ 02971 02972 /* We must take into account that our sample actually represents 02973 also the pages used for external storage of fields (those pages are 02974 included in index->stat_n_leaf_pages) */ 02975 02976 for (j = 0; j <= n_cols; j++) { 02977 index->stat_n_diff_key_vals[j] = 02978 (n_diff[j] 02979 * (ib_longlong)index->stat_n_leaf_pages 02980 + BTR_KEY_VAL_ESTIMATE_N_PAGES - 1 02981 + total_external_size 02982 + not_empty_flag) 02983 / (BTR_KEY_VAL_ESTIMATE_N_PAGES 02984 + total_external_size); 02985 02986 /* If the tree is small, smaller than < 02987 10 * BTR_KEY_VAL_ESTIMATE_N_PAGES + total_external_size, then 02988 the above estimate is ok. For bigger trees it is common that we 02989 do not see any borders between key values in the few pages 02990 we pick. But still there may be BTR_KEY_VAL_ESTIMATE_N_PAGES 02991 different key values, or even more. Let us try to approximate 02992 that: */ 02993 02994 add_on = index->stat_n_leaf_pages / 02995 (10 * (BTR_KEY_VAL_ESTIMATE_N_PAGES + total_external_size)); 02996 02997 if (add_on > BTR_KEY_VAL_ESTIMATE_N_PAGES) { 02998 add_on = BTR_KEY_VAL_ESTIMATE_N_PAGES; 02999 } 03000 03001 index->stat_n_diff_key_vals[j] += add_on; 03002 } 03003 03004 mem_free(n_diff); 03005 if (UNIV_LIKELY_NULL(heap)) { 03006 mem_heap_free(heap); 03007 } 03008 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_free_externally_stored_field | ( | dict_index_t * | index, | |
| byte * | data, | |||
| ulint | local_len, | |||
| ibool | do_not_free_inherited, | |||
| mtr_t * | local_mtr | |||
| ) |
Definition at line 3258 of file btr0cur.c.
References FALSE, n, rec_offs_n_fields(), rec_offs_nth_extern(), TRUE, upd_get_n_fields(), upd_get_nth_field(), and update.
Referenced by btr_cur_pessimistic_update(), row_upd_store_row(), and trx_undo_prev_version_build().
03260 : number of values stored in ext_vect */ 03261 ulint* ext_vect,/* in: array of ulints, must be preallocated 03262 to have space for all fields in rec */ 03263 const ulint* offsets,/* in: array returned by rec_get_offsets() */ 03264 upd_t* update) /* in: update vector or NULL */ 03265 { 03266 ulint n_pushed = 0; 03267 ibool is_updated; 03268 ulint n; 03269 ulint j; 03270 ulint i; 03271 03272 if (update) { 03273 n = upd_get_n_fields(update); 03274 03275 for (i = 0; i < n; i++) { 03276 03277 if (upd_get_nth_field(update, i)->extern_storage) { 03278 03279 ext_vect[n_pushed] = 03280 upd_get_nth_field(update, i)->field_no; 03281 03282 n_pushed++; 03283 } 03284 } 03285 } 03286 03287 n = rec_offs_n_fields(offsets); 03288 03289 for (i = 0; i < n; i++) { 03290 if (rec_offs_nth_extern(offsets, i)) { 03291 03292 /* Check it is not in updated fields */ 03293 is_updated = FALSE; 03294 03295 if (update) { 03296 for (j = 0; j < upd_get_n_fields(update); 03297 j++) { 03298 if (upd_get_nth_field(update, j) 03299 ->field_no == i) { 03300 is_updated = TRUE; 03301 } 03302 } 03303 } 03304 03305 if (!is_updated) { 03306 ext_vect[n_pushed] = i; 03307 n_pushed++; 03308 } 03309 } 03310 } 03311 03312 return(n_pushed); 03313 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* btr_rec_copy_externally_stored_field | ( | rec_t * | rec, | |
| const ulint * | offsets, | |||
| ulint | no, | |||
| ulint * | len, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 3818 of file btr0cur.c.
References btr_copy_externally_stored_field(), NULL, rec_get_nth_field(), rec_offs_nth_extern(), rec_offs_validate(), ut_a, and ut_ad.
Referenced by row_build(), and row_sel_fetch_columns().
03820 : the field copied to heap */ 03821 rec_t* rec, /* in: record */ 03822 const ulint* offsets,/* in: array returned by rec_get_offsets() */ 03823 ulint no, /* in: field number */ 03824 ulint* len, /* out: length of the field */ 03825 mem_heap_t* heap) /* in: mem heap */ 03826 { 03827 ulint local_len; 03828 byte* data; 03829 03830 ut_ad(rec_offs_validate(rec, NULL, offsets)); 03831 ut_a(rec_offs_nth_extern(offsets, no)); 03832 03833 /* An externally stored field can contain some initial 03834 data from the field, and in the last 20 bytes it has the 03835 space id, page number, and offset where the rest of the 03836 field data is stored, and the data length in addition to 03837 the data stored locally. We may need to store some data 03838 locally to get the local record length above the 128 byte 03839 limit so that field offsets are stored in two bytes, and 03840 the extern bit is available in those two bytes. */ 03841 03842 data = rec_get_nth_field(rec, offsets, no, &local_len); 03843 03844 return(btr_copy_externally_stored_field(len, data, local_len, heap)); 03845 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_rec_free_externally_stored_fields | ( | dict_index_t * | index, | |
| rec_t * | rec, | |||
| const ulint * | offsets, | |||
| ibool | do_not_free_inherited, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 3643 of file btr0cur.c.
References btr_free_externally_stored_field(), buf_block_align(), dict_table_is_comp(), index(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, rec_get_nth_field(), rec_offs_comp(), rec_offs_n_fields(), rec_offs_nth_extern(), rec_offs_validate(), and ut_ad.
Referenced by btr_cur_pessimistic_delete().
03645 : index of the data, the index 03646 tree MUST be X-latched */ 03647 rec_t* rec, /* in: record */ 03648 const ulint* offsets,/* in: rec_get_offsets(rec, index) */ 03649 ibool do_not_free_inherited,/* in: TRUE if called in a 03650 rollback and we do not want to free 03651 inherited fields */ 03652 mtr_t* mtr) /* in: mini-transaction handle which contains 03653 an X-latch to record page and to the index 03654 tree */ 03655 { 03656 ulint n_fields; 03657 byte* data; 03658 ulint len; 03659 ulint i; 03660 03661 ut_ad(rec_offs_validate(rec, index, offsets)); 03662 ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), 03663 MTR_MEMO_PAGE_X_FIX)); 03664 /* Free possible externally stored fields in the record */ 03665 03666 ut_ad(dict_table_is_comp(index->table) == !!rec_offs_comp(offsets)); 03667 n_fields = rec_offs_n_fields(offsets); 03668 03669 for (i = 0; i < n_fields; i++) { 03670 if (rec_offs_nth_extern(offsets, i)) { 03671 03672 data = rec_get_nth_field(rec, offsets, i, &len); 03673 btr_free_externally_stored_field(index, data, len, 03674 do_not_free_inherited, mtr); 03675 } 03676 } 03677 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint btr_store_big_rec_extern_fields | ( | dict_index_t * | index, | |
| rec_t * | rec, | |||
| const ulint * | offsets, | |||
| big_rec_t * | big_rec_vec, | |||
| mtr_t * | local_mtr | |||
| ) |
Definition at line 45 of file btr0cur.c.
Referenced by btr_cur_search_to_nth_level(), srv_printf_innodb_monitor(), and srv_refresh_innodb_monitor_stats().
Definition at line 47 of file btr0cur.c.
Referenced by srv_printf_innodb_monitor(), and srv_refresh_innodb_monitor_stats().
Definition at line 46 of file btr0cur.c.
Referenced by btr_cur_search_to_nth_level(), srv_printf_innodb_monitor(), and srv_refresh_innodb_monitor_stats().
Definition at line 48 of file btr0cur.c.
Referenced by srv_printf_innodb_monitor(), and srv_refresh_innodb_monitor_stats().
1.4.7

