#include "ibuf0ibuf.h"#include "buf0buf.h"#include "buf0rea.h"#include "fsp0fsp.h"#include "trx0sys.h"#include "fil0fil.h"#include "thr0loc.h"#include "rem0rec.h"#include "btr0cur.h"#include "btr0pcur.h"#include "btr0btr.h"#include "sync0sync.h"#include "dict0boot.h"#include "fut0lst.h"#include "lock0lock.h"#include "log0recv.h"#include "que0que.h"Include dependency graph for ibuf0ibuf.c:

Go to the source code of this file.
| #define IBUF_BITMAP PAGE_DATA |
Definition at line 159 of file ibuf0ibuf.c.
Referenced by ibuf_bitmap_page_get_bits(), ibuf_bitmap_page_init(), and ibuf_bitmap_page_set_bits().
| #define IBUF_BITMAP_BUFFERED 2 |
Definition at line 163 of file ibuf0ibuf.c.
Referenced by ibuf_bitmap_page_set_bits(), ibuf_insert_low(), and ibuf_merge_or_delete_for_page().
| #define IBUF_BITMAP_FREE 0 |
Definition at line 162 of file ibuf0ibuf.c.
Referenced by ibuf_bitmap_page_get_bits(), ibuf_bitmap_page_set_bits(), ibuf_insert_low(), ibuf_insert_to_index_page(), ibuf_merge_or_delete_for_page(), ibuf_set_free_bits(), and ibuf_set_free_bits_low().
| #define IBUF_BITMAP_IBUF 3 |
Definition at line 164 of file ibuf0ibuf.c.
Referenced by ibuf_add_free_page(), ibuf_page(), ibuf_page_low(), and ibuf_remove_free_page().
| #define IBUF_BITS_PER_PAGE 4 |
Definition at line 169 of file ibuf0ibuf.c.
Referenced by ibuf_bitmap_page_get_bits(), ibuf_bitmap_page_init(), and ibuf_bitmap_page_set_bits().
| #define IBUF_CONTRACT_DO_NOT_INSERT 10 |
| #define IBUF_CONTRACT_ON_INSERT_NON_SYNC 0 |
| #define IBUF_CONTRACT_ON_INSERT_SYNC 5 |
| #define IBUF_MAX_N_PAGES_MERGED IBUF_MERGE_AREA |
Definition at line 193 of file ibuf0ibuf.c.
Referenced by ibuf_contract_ext(), ibuf_get_merge_page_nos(), and ibuf_insert_low().
| #define IBUF_MERGE_AREA 8 |
| #define IBUF_MERGE_THRESHOLD 4 |
| #define IBUF_POOL_SIZE_PER_MAX_SIZE 2 |
| static ulint ibuf_add_free_page | ( | ulint | space, | |
| ibuf_data_t * | ibuf_data | |||
| ) | [static] |
Definition at line 1623 of file ibuf0ibuf.c.
References buf_page_get, DB_STRONG_FAIL, DB_SUCCESS, FIL_NULL, FIL_PAGE_IBUF_FREE_LIST, FIL_PAGE_TYPE, fil_space_get_latch(), flst_add_last(), fseg_alloc_free_page(), FSP_UP, ibuf_bitmap_get_map_page(), IBUF_BITMAP_IBUF, ibuf_bitmap_page_set_bits(), ibuf_enter(), ibuf_exit(), IBUF_HEADER, ibuf_header_page_get(), ibuf_mutex, ibuf_tree_root_get(), IBUF_TREE_SEG_HEADER, MLOG_2BYTES, mlog_write_ulint(), mtr_commit(), mtr_start(), mtr_x_lock, mutex_enter, mutex_exit(), PAGE_BTR_IBUF_FREE_LIST, PAGE_BTR_IBUF_FREE_LIST_NODE, PAGE_HEADER, page_t, RW_X_LATCH, SYNC_TREE_NODE_NEW, TRUE, and ut_a.
Referenced by ibuf_insert_low().
01625 : DB_SUCCESS, or DB_STRONG_FAIL 01626 if no space left */ 01627 ulint space, /* in: space id */ 01628 ibuf_data_t* ibuf_data) /* in: ibuf data for the space */ 01629 { 01630 mtr_t mtr; 01631 page_t* header_page; 01632 ulint page_no; 01633 page_t* page; 01634 page_t* root; 01635 page_t* bitmap_page; 01636 01637 ut_a(space == 0); 01638 01639 mtr_start(&mtr); 01640 01641 /* Acquire the fsp latch before the ibuf header, obeying the latching 01642 order */ 01643 mtr_x_lock(fil_space_get_latch(space), &mtr); 01644 01645 header_page = ibuf_header_page_get(space, &mtr); 01646 01647 /* Allocate a new page: NOTE that if the page has been a part of a 01648 non-clustered index which has subsequently been dropped, then the 01649 page may have buffered inserts in the insert buffer, and these 01650 should be deleted from there. These get deleted when the page 01651 allocation creates the page in buffer. Thus the call below may end 01652 up calling the insert buffer routines and, as we yet have no latches 01653 to insert buffer tree pages, these routines can run without a risk 01654 of a deadlock. This is the reason why we created a special ibuf 01655 header page apart from the ibuf tree. */ 01656 01657 page_no = fseg_alloc_free_page(header_page + IBUF_HEADER 01658 + IBUF_TREE_SEG_HEADER, 0, FSP_UP, 01659 &mtr); 01660 if (page_no == FIL_NULL) { 01661 mtr_commit(&mtr); 01662 01663 return(DB_STRONG_FAIL); 01664 } 01665 01666 page = buf_page_get(space, page_no, RW_X_LATCH, &mtr); 01667 01668 #ifdef UNIV_SYNC_DEBUG 01669 buf_page_dbg_add_level(page, SYNC_TREE_NODE_NEW); 01670 #endif /* UNIV_SYNC_DEBUG */ 01671 01672 ibuf_enter(); 01673 01674 mutex_enter(&ibuf_mutex); 01675 01676 root = ibuf_tree_root_get(ibuf_data, space, &mtr); 01677 01678 /* Add the page to the free list and update the ibuf size data */ 01679 01680 flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, 01681 page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr); 01682 01683 mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_IBUF_FREE_LIST, 01684 MLOG_2BYTES, &mtr); 01685 01686 ibuf_data->seg_size++; 01687 ibuf_data->free_list_len++; 01688 01689 /* Set the bit indicating that this page is now an ibuf tree page 01690 (level 2 page) */ 01691 01692 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, &mtr); 01693 01694 ibuf_bitmap_page_set_bits(bitmap_page, page_no, IBUF_BITMAP_IBUF, 01695 TRUE, &mtr); 01696 mtr_commit(&mtr); 01697 01698 mutex_exit(&ibuf_mutex); 01699 01700 ibuf_exit(); 01701 01702 return(DB_SUCCESS); 01703 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 729 of file ibuf0ibuf.c.
References buf_page_get, ibuf_bitmap_page_no_calc(), page_t, RW_X_LATCH, and SYNC_IBUF_BITMAP.
Referenced by ibuf_add_free_page(), ibuf_insert_low(), ibuf_insert_to_index_page(), ibuf_merge_or_delete_for_page(), ibuf_page(), ibuf_page_low(), ibuf_remove_free_page(), ibuf_set_free_bits(), and ibuf_set_free_bits_low().
00731 : bitmap page where the file page is mapped, 00732 that is, the bitmap page containing the descriptor 00733 bits for the file page; the bitmap page is 00734 x-latched */ 00735 ulint space, /* in: space id of the file page */ 00736 ulint page_no,/* in: page number of the file page */ 00737 mtr_t* mtr) /* in: mtr */ 00738 { 00739 page_t* page; 00740 00741 page = buf_page_get(space, ibuf_bitmap_page_no_calc(page_no), 00742 RW_X_LATCH, mtr); 00743 #ifdef UNIV_SYNC_DEBUG 00744 buf_page_dbg_add_level(page, SYNC_IBUF_BITMAP); 00745 #endif /* UNIV_SYNC_DEBUG */ 00746 00747 return(page); 00748 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ulint ibuf_bitmap_page_get_bits | ( | page_t * | page, | |
| ulint | page_no, | |||
| ulint | bit, | |||
| mtr_t *mtr | __attribute__((unused)) | |||
| ) |
Definition at line 614 of file ibuf0ibuf.c.
References buf_block_align(), IBUF_BITMAP, IBUF_BITMAP_FREE, IBUF_BITS_PER_PAGE, mach_read_from_1(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, UNIV_PAGE_SIZE, ut_ad, ut_bit_get_nth(), value, and XDES_DESCRIBED_PER_PAGE.
Referenced by ibuf_insert_low(), ibuf_insert_to_index_page(), ibuf_merge_or_delete_for_page(), ibuf_page(), ibuf_page_low(), and ibuf_set_free_bits().
00616 : value of bits */ 00617 page_t* page, /* in: bitmap page */ 00618 ulint page_no,/* in: page whose bits to get */ 00619 ulint bit, /* in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ... */ 00620 mtr_t* mtr __attribute__((unused))) /* in: mtr containing an 00621 x-latch to the bitmap 00622 page */ 00623 { 00624 ulint byte_offset; 00625 ulint bit_offset; 00626 ulint map_byte; 00627 ulint value; 00628 00629 ut_ad(bit < IBUF_BITS_PER_PAGE); 00630 #if IBUF_BITS_PER_PAGE % 2 00631 # error "IBUF_BITS_PER_PAGE % 2 != 0" 00632 #endif 00633 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 00634 MTR_MEMO_PAGE_X_FIX)); 00635 00636 bit_offset = (page_no % XDES_DESCRIBED_PER_PAGE) * IBUF_BITS_PER_PAGE 00637 + bit; 00638 00639 byte_offset = bit_offset / 8; 00640 bit_offset = bit_offset % 8; 00641 00642 ut_ad(byte_offset + IBUF_BITMAP < UNIV_PAGE_SIZE); 00643 00644 map_byte = mach_read_from_1(page + IBUF_BITMAP + byte_offset); 00645 00646 value = ut_bit_get_nth(map_byte, bit_offset); 00647 00648 if (bit == IBUF_BITMAP_FREE) { 00649 ut_ad(bit_offset + 1 < 8); 00650 00651 value = value * 2 + ut_bit_get_nth(map_byte, bit_offset + 1); 00652 } 00653 00654 return(value); 00655 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 566 of file ibuf0ibuf.c.
References FIL_PAGE_IBUF_BITMAP, fil_page_set_type(), IBUF_BITMAP, IBUF_BITS_PER_PAGE, memset, MLOG_IBUF_BITMAP_INIT, mlog_write_initial_log_record(), and XDES_DESCRIBED_PER_PAGE.
Referenced by fsp_fill_free_list(), and ibuf_parse_bitmap_init().
00568 : bitmap page */ 00569 mtr_t* mtr) /* in: mtr */ 00570 { 00571 ulint bit_offset; 00572 ulint byte_offset; 00573 00574 /* Write all zeros to the bitmap */ 00575 00576 bit_offset = XDES_DESCRIBED_PER_PAGE * IBUF_BITS_PER_PAGE; 00577 00578 byte_offset = bit_offset / 8 + 1; /* better: (bit_offset + 7) / 8 */ 00579 00580 fil_page_set_type(page, FIL_PAGE_IBUF_BITMAP); 00581 00582 memset(page + IBUF_BITMAP, 0, byte_offset); 00583 00584 /* The remaining area (up to the page trailer) is uninitialized. */ 00585 00586 mlog_write_initial_log_record(page, MLOG_IBUF_BITMAP_INIT, mtr); 00587 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 713 of file ibuf0ibuf.c.
References FSP_IBUF_BITMAP_OFFSET, and XDES_DESCRIBED_PER_PAGE.
Referenced by ibuf_bitmap_get_map_page().
00715 : the bitmap page number where 00716 the file page is mapped */ 00717 ulint page_no) /* in: tablespace page number */ 00718 { 00719 return(FSP_IBUF_BITMAP_OFFSET 00720 + XDES_DESCRIBED_PER_PAGE 00721 * (page_no / XDES_DESCRIBED_PER_PAGE)); 00722 }
Here is the caller graph for this function:

| static void ibuf_bitmap_page_set_bits | ( | page_t * | page, | |
| ulint | page_no, | |||
| ulint | bit, | |||
| ulint | val, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 661 of file ibuf0ibuf.c.
References buf_block_align(), buf_frame_get_space_id(), FALSE, IBUF_BITMAP, IBUF_BITMAP_BUFFERED, IBUF_BITMAP_FREE, IBUF_BITS_PER_PAGE, mach_read_from_1(), MLOG_1BYTE, mlog_write_ulint(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, UNIV_PAGE_SIZE, ut_a, ut_ad, ut_bit_set_nth(), and XDES_DESCRIBED_PER_PAGE.
Referenced by ibuf_add_free_page(), ibuf_insert_low(), ibuf_merge_or_delete_for_page(), ibuf_remove_free_page(), ibuf_set_free_bits(), and ibuf_set_free_bits_low().
00663 : bitmap page */ 00664 ulint page_no,/* in: page whose bits to set */ 00665 ulint bit, /* in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ... */ 00666 ulint val, /* in: value to set */ 00667 mtr_t* mtr) /* in: mtr containing an x-latch to the bitmap page */ 00668 { 00669 ulint byte_offset; 00670 ulint bit_offset; 00671 ulint map_byte; 00672 00673 ut_ad(bit < IBUF_BITS_PER_PAGE); 00674 #if IBUF_BITS_PER_PAGE % 2 00675 # error "IBUF_BITS_PER_PAGE % 2 != 0" 00676 #endif 00677 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 00678 MTR_MEMO_PAGE_X_FIX)); 00679 #ifdef UNIV_IBUF_DEBUG 00680 ut_a((bit != IBUF_BITMAP_BUFFERED) || (val != FALSE) 00681 || (0 == ibuf_count_get(buf_frame_get_space_id(page), 00682 page_no))); 00683 #endif 00684 bit_offset = (page_no % XDES_DESCRIBED_PER_PAGE) * IBUF_BITS_PER_PAGE 00685 + bit; 00686 00687 byte_offset = bit_offset / 8; 00688 bit_offset = bit_offset % 8; 00689 00690 ut_ad(byte_offset + IBUF_BITMAP < UNIV_PAGE_SIZE); 00691 00692 map_byte = mach_read_from_1(page + IBUF_BITMAP + byte_offset); 00693 00694 if (bit == IBUF_BITMAP_FREE) { 00695 ut_ad(bit_offset + 1 < 8); 00696 ut_ad(val <= 3); 00697 00698 map_byte = ut_bit_set_nth(map_byte, bit_offset, val / 2); 00699 map_byte = ut_bit_set_nth(map_byte, bit_offset + 1, val % 2); 00700 } else { 00701 ut_ad(val <= 1); 00702 map_byte = ut_bit_set_nth(map_byte, bit_offset, val); 00703 } 00704 00705 mlog_write_ulint(page + IBUF_BITMAP + byte_offset, map_byte, 00706 MLOG_1BYTE, mtr); 00707 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static dtuple_t* ibuf_build_entry_from_ibuf_rec | ( | rec_t * | ibuf_rec, | |
| mem_heap_t * | heap, | |||
| dict_index_t ** | pindex | |||
| ) | [static] |
Definition at line 1177 of file ibuf0ibuf.c.
References data, DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE, DATA_ORDER_NULL_TYPE_BUF_SIZE, dfield_get_type(), dfield_set_data(), dtuple_create(), dtuple_get_nth_field(), dtype_new_read_for_order_and_null_size(), dtype_read_for_order_and_null_size(), FALSE, ibuf_dummy_index_add_col(), ibuf_dummy_index_create(), index(), rec_get_n_fields_old(), rec_get_nth_field_old(), trx_doublewrite_must_reset_space_ids, trx_sys_multiple_tablespace_format, and ut_a.
Referenced by ibuf_merge_or_delete_for_page(), and ibuf_rec_get_volume().
01179 : entry to insert to 01180 a non-clustered index; NOTE that 01181 as we copy pointers to fields in 01182 ibuf_rec, the caller must hold a 01183 latch to the ibuf_rec page as long 01184 as the entry is used! */ 01185 rec_t* ibuf_rec, /* in: record in an insert buffer */ 01186 mem_heap_t* heap, /* in: heap where built */ 01187 dict_index_t** pindex) /* out, own: dummy index that 01188 describes the entry */ 01189 { 01190 dtuple_t* tuple; 01191 dfield_t* field; 01192 ulint n_fields; 01193 byte* types; 01194 const byte* data; 01195 ulint len; 01196 ulint i; 01197 dict_index_t* index; 01198 01199 data = rec_get_nth_field_old(ibuf_rec, 1, &len); 01200 01201 if (len > 1) { 01202 /* This a < 4.1.x format record */ 01203 01204 ut_a(trx_doublewrite_must_reset_space_ids); 01205 ut_a(!trx_sys_multiple_tablespace_format); 01206 01207 n_fields = rec_get_n_fields_old(ibuf_rec) - 2; 01208 tuple = dtuple_create(heap, n_fields); 01209 types = rec_get_nth_field_old(ibuf_rec, 1, &len); 01210 01211 ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE); 01212 01213 for (i = 0; i < n_fields; i++) { 01214 field = dtuple_get_nth_field(tuple, i); 01215 01216 data = rec_get_nth_field_old(ibuf_rec, i + 2, &len); 01217 01218 dfield_set_data(field, data, len); 01219 01220 dtype_read_for_order_and_null_size( 01221 dfield_get_type(field), 01222 types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE); 01223 } 01224 01225 *pindex = ibuf_dummy_index_create(n_fields, FALSE); 01226 return(tuple); 01227 } 01228 01229 /* This a >= 4.1.x format record */ 01230 01231 ut_a(trx_sys_multiple_tablespace_format); 01232 ut_a(*data == 0); 01233 ut_a(rec_get_n_fields_old(ibuf_rec) > 4); 01234 01235 n_fields = rec_get_n_fields_old(ibuf_rec) - 4; 01236 01237 tuple = dtuple_create(heap, n_fields); 01238 01239 types = rec_get_nth_field_old(ibuf_rec, 3, &len); 01240 01241 ut_a(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE <= 1); 01242 index = ibuf_dummy_index_create(n_fields, 01243 len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE); 01244 01245 if (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) { 01246 /* compact record format */ 01247 len--; 01248 ut_a(*types == 0); 01249 types++; 01250 } 01251 01252 ut_a(len == n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE); 01253 01254 for (i = 0; i < n_fields; i++) { 01255 field = dtuple_get_nth_field(tuple, i); 01256 01257 data = rec_get_nth_field_old(ibuf_rec, i + 4, &len); 01258 01259 dfield_set_data(field, data, len); 01260 01261 dtype_new_read_for_order_and_null_size( 01262 dfield_get_type(field), 01263 types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE); 01264 01265 ibuf_dummy_index_add_col(index, dfield_get_type(field), len); 01266 } 01267 01268 *pindex = index; 01269 return(tuple); 01270 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint ibuf_contract | ( | ibool | sync | ) |
Definition at line 2181 of file ibuf0ibuf.c.
References ibuf_contract_ext().
Referenced by ibuf_contract_after_insert(), and ibuf_insert_low().
02183 : a lower limit for the combined size in bytes 02184 of entries which will be merged from ibuf trees to the 02185 pages read, 0 if ibuf is empty */ 02186 ibool sync) /* in: TRUE if the caller wants to wait for the 02187 issued read with the highest tablespace address 02188 to complete */ 02189 { 02190 ulint n_pages; 02191 02192 return(ibuf_contract_ext(&n_pages, sync)); 02193 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void ibuf_contract_after_insert | ( | ulint | entry_size | ) |
Definition at line 2234 of file ibuf0ibuf.c.
References FALSE, ibuf, ibuf_contract(), IBUF_CONTRACT_ON_INSERT_NON_SYNC, IBUF_CONTRACT_ON_INSERT_SYNC, ibuf_mutex, mutex_enter, mutex_exit(), and TRUE.
Referenced by ibuf_insert_low().
02236 : size of a record which was inserted 02237 into an ibuf tree */ 02238 { 02239 ibool sync; 02240 ulint sum_sizes; 02241 ulint size; 02242 02243 mutex_enter(&ibuf_mutex); 02244 02245 if (ibuf->size < ibuf->max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) { 02246 mutex_exit(&ibuf_mutex); 02247 02248 return; 02249 } 02250 02251 sync = FALSE; 02252 02253 if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_ON_INSERT_SYNC) { 02254 02255 sync = TRUE; 02256 } 02257 02258 mutex_exit(&ibuf_mutex); 02259 02260 /* Contract at least entry_size many bytes */ 02261 sum_sizes = 0; 02262 size = 1; 02263 02264 while ((size > 0) && (sum_sizes < entry_size)) { 02265 02266 size = ibuf_contract(sync); 02267 sum_sizes += size; 02268 } 02269 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2061 of file ibuf0ibuf.c.
References data, FALSE, ibuf, ibuf_inside(), IBUF_MAX_N_PAGES_MERGED, ibuf_mutex, ibuf_rnd, ibuf_validate_low(), mutex_enter, mutex_exit(), NULL, TRUE, ut_ad, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by ibuf_contract(), and ibuf_contract_for_n_pages().
02063 : a lower limit for the combined size in bytes 02064 of entries which will be merged from ibuf trees to the 02065 pages read, 0 if ibuf is empty */ 02066 ulint* n_pages,/* out: number of pages to which merged */ 02067 ibool sync) /* in: TRUE if the caller wants to wait for the 02068 issued read with the highest tablespace address 02069 to complete */ 02070 { 02071 ulint rnd_pos; 02072 ibuf_data_t* data; 02073 btr_pcur_t pcur; 02074 ulint space; 02075 ibool all_trees_empty; 02076 ulint page_nos[IBUF_MAX_N_PAGES_MERGED]; 02077 ulint space_ids[IBUF_MAX_N_PAGES_MERGED]; 02078 ib_longlong space_versions[IBUF_MAX_N_PAGES_MERGED]; 02079 ulint n_stored; 02080 ulint sum_sizes; 02081 mtr_t mtr; 02082 02083 *n_pages = 0; 02084 loop: 02085 ut_ad(!ibuf_inside()); 02086 02087 mutex_enter(&ibuf_mutex); 02088 02089 ut_ad(ibuf_validate_low()); 02090 02091 /* Choose an ibuf tree at random (though there really is only one tree 02092 in the current implementation) */ 02093 ibuf_rnd += 865558671; 02094 02095 rnd_pos = ibuf_rnd % ibuf->size; 02096 02097 all_trees_empty = TRUE; 02098 02099 data = UT_LIST_GET_FIRST(ibuf->data_list); 02100 02101 for (;;) { 02102 if (!data->empty) { 02103 all_trees_empty = FALSE; 02104 02105 if (rnd_pos < data->size) { 02106 02107 break; 02108 } 02109 02110 rnd_pos -= data->size; 02111 } 02112 02113 data = UT_LIST_GET_NEXT(data_list, data); 02114 02115 if (data == NULL) { 02116 if (all_trees_empty) { 02117 mutex_exit(&ibuf_mutex); 02118 02119 return(0); 02120 } 02121 02122 data = UT_LIST_GET_FIRST(ibuf->data_list); 02123 } 02124 } 02125 02126 ut_ad(data); 02127 02128 space = data->index->space; 02129 02130 ut_a(space == 0); /* We currently only have an ibuf tree in 02131 space 0 */ 02132 mtr_start(&mtr); 02133 02134 ibuf_enter(); 02135 02136 /* Open a cursor to a randomly chosen leaf of the tree, at a random 02137 position within the leaf */ 02138 02139 btr_pcur_open_at_rnd_pos(data->index, BTR_SEARCH_LEAF, &pcur, &mtr); 02140 02141 if (0 == page_get_n_recs(btr_pcur_get_page(&pcur))) { 02142 02143 /* This tree is empty */ 02144 02145 data->empty = TRUE; 02146 02147 ibuf_exit(); 02148 02149 mtr_commit(&mtr); 02150 btr_pcur_close(&pcur); 02151 02152 mutex_exit(&ibuf_mutex); 02153 02154 goto loop; 02155 } 02156 02157 mutex_exit(&ibuf_mutex); 02158 02159 sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur), 02160 space_ids, space_versions, page_nos, &n_stored); 02161 #ifdef UNIV_IBUF_DEBUG 02162 /* fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n", 02163 sync, n_stored, sum_sizes); */ 02164 #endif 02165 ibuf_exit(); 02166 02167 mtr_commit(&mtr); 02168 btr_pcur_close(&pcur); 02169 02170 buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos, 02171 n_stored); 02172 *n_pages = n_stored; 02173 02174 return(sum_sizes + 1); 02175 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2199 of file ibuf0ibuf.c.
References ibuf_contract_ext().
Referenced by srv_master_thread().
02201 : a lower limit for the combined size in bytes 02202 of entries which will be merged from ibuf trees to the 02203 pages read, 0 if ibuf is empty */ 02204 ibool sync, /* in: TRUE if the caller wants to wait for the 02205 issued read with the highest tablespace address 02206 to complete */ 02207 ulint n_pages)/* in: try to read at least this many pages to 02208 the buffer pool and merge the ibuf contents to 02209 them */ 02210 { 02211 ulint sum_bytes = 0; 02212 ulint sum_pages = 0; 02213 ulint n_bytes; 02214 ulint n_pag2; 02215 02216 while (sum_pages < n_pages) { 02217 n_bytes = ibuf_contract_ext(&n_pag2, sync); 02218 02219 if (n_bytes == 0) { 02220 return(sum_bytes); 02221 } 02222 02223 sum_bytes += n_bytes; 02224 sum_pages += n_pag2; 02225 } 02226 02227 return(sum_bytes); 02228 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool ibuf_data_enough_free_for_insert | ( | ibuf_data_t * | data | ) |
Definition at line 1573 of file ibuf0ibuf.c.
References FALSE, ibuf_mutex, TRUE, and ut_ad.
Referenced by ibuf_insert_low().
01575 : TRUE if enough free pages in list */ 01576 ibuf_data_t* data) /* in: ibuf data for the space */ 01577 { 01578 #ifdef UNIV_SYNC_DEBUG 01579 ut_ad(mutex_own(&ibuf_mutex)); 01580 #endif /* UNIV_SYNC_DEBUG */ 01581 01582 /* We want a big margin of free pages, because a B-tree can sometimes 01583 grow in size also if records are deleted from it, as the node pointers 01584 can change, and we must make sure that we are able to delete the 01585 inserts buffered for pages that we read to the buffer pool, without 01586 any risk of running out of free space in the insert buffer. */ 01587 01588 if (data->free_list_len >= data->size / 2 + 3 * data->height) { 01589 01590 return(TRUE); 01591 } 01592 01593 return(FALSE); 01594 }
Here is the caller graph for this function:

| ibuf_data_t* ibuf_data_init_for_space | ( | ulint | space | ) |
Definition at line 458 of file ibuf0ibuf.c.
References buf, buf_page_get, data, DATA_BINARY, DICT_CLUSTERED, DICT_IBUF, DICT_IBUF_ID_MIN, dict_index_add_to_cache(), dict_mem_index_add_field(), dict_mem_index_create(), dict_mem_table_add_col(), dict_mem_table_create(), dict_table_add_to_cache(), dict_table_get_first_index(), DICT_UNIVERSAL, fil_space_get_latch(), fseg_n_reserved_pages(), FSP_IBUF_TREE_ROOT_PAGE_NO, ibuf, ibuf_data_sizes_update(), ibuf_enter(), ibuf_exit(), IBUF_HEADER, ibuf_header_page_get(), ibuf_mutex, IBUF_TREE_SEG_HEADER, dict_table_struct::id, index(), mem_alloc, mtr_commit(), mtr_start(), mtr_x_lock, mutex_enter, mutex_exit(), NULL, page_t, RW_X_LATCH, SYNC_TREE_NODE, ut_a, ut_ad, ut_dulint_add(), and UT_LIST_ADD_LAST.
Referenced by fil_ibuf_init_at_db_start().
00460 : ibuf data struct, linked to the list 00461 in ibuf control structure */ 00462 ulint space) /* in: space id */ 00463 { 00464 ibuf_data_t* data; 00465 page_t* root; 00466 page_t* header_page; 00467 mtr_t mtr; 00468 char buf[50]; 00469 dict_table_t* table; 00470 dict_index_t* index; 00471 ulint n_used; 00472 00473 ut_a(space == 0); 00474 00475 #ifdef UNIV_LOG_DEBUG 00476 if (space % 2 == 1) { 00477 00478 fputs("No ibuf op in replicate space\n", stderr); 00479 00480 return(NULL); 00481 } 00482 #endif 00483 data = mem_alloc(sizeof(ibuf_data_t)); 00484 00485 data->space = space; 00486 00487 mtr_start(&mtr); 00488 00489 mutex_enter(&ibuf_mutex); 00490 00491 mtr_x_lock(fil_space_get_latch(space), &mtr); 00492 00493 header_page = ibuf_header_page_get(space, &mtr); 00494 00495 fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 00496 &n_used, &mtr); 00497 ibuf_enter(); 00498 00499 ut_ad(n_used >= 2); 00500 00501 data->seg_size = n_used; 00502 00503 root = buf_page_get(space, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, 00504 &mtr); 00505 #ifdef UNIV_SYNC_DEBUG 00506 buf_page_dbg_add_level(root, SYNC_TREE_NODE); 00507 #endif /* UNIV_SYNC_DEBUG */ 00508 00509 data->size = 0; 00510 data->n_inserts = 0; 00511 data->n_merges = 0; 00512 data->n_merged_recs = 0; 00513 00514 ibuf_data_sizes_update(data, root, &mtr); 00515 /* 00516 if (!data->empty) { 00517 fprintf(stderr, 00518 "InnoDB: index entries found in the insert buffer\n"); 00519 } else { 00520 fprintf(stderr, 00521 "InnoDB: insert buffer empty\n"); 00522 } 00523 */ 00524 mutex_exit(&ibuf_mutex); 00525 00526 mtr_commit(&mtr); 00527 00528 ibuf_exit(); 00529 00530 sprintf(buf, "SYS_IBUF_TABLE_%lu", (ulong) space); 00531 /* use old-style record format for the insert buffer */ 00532 table = dict_mem_table_create(buf, space, 2, 0); 00533 00534 dict_mem_table_add_col(table, "PAGE_NO", DATA_BINARY, 0, 0, 0); 00535 dict_mem_table_add_col(table, "TYPES", DATA_BINARY, 0, 0, 0); 00536 00537 table->id = ut_dulint_add(DICT_IBUF_ID_MIN, space); 00538 00539 dict_table_add_to_cache(table); 00540 00541 index = dict_mem_index_create(buf, "CLUST_IND", space, 00542 DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,2); 00543 00544 dict_mem_index_add_field(index, "PAGE_NO", 0); 00545 dict_mem_index_add_field(index, "TYPES", 0); 00546 00547 index->id = ut_dulint_add(DICT_IBUF_ID_MIN, space); 00548 00549 dict_index_add_to_cache(table, index, FSP_IBUF_TREE_ROOT_PAGE_NO); 00550 00551 data->index = dict_table_get_first_index(table); 00552 00553 mutex_enter(&ibuf_mutex); 00554 00555 UT_LIST_ADD_LAST(data_list, ibuf->data_list, data); 00556 00557 mutex_exit(&ibuf_mutex); 00558 00559 return(data); 00560 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void ibuf_data_sizes_update | ( | ibuf_data_t * | data, | |
| page_t * | root, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 413 of file ibuf0ibuf.c.
References btr_page_get_level(), FALSE, flst_get_len(), ibuf, ibuf_mutex, PAGE_BTR_IBUF_FREE_LIST, page_get_n_recs(), PAGE_HEADER, TRUE, and ut_ad.
Referenced by ibuf_data_init_for_space(), ibuf_delete_rec(), and ibuf_insert_low().
00415 : ibuf data struct */ 00416 page_t* root, /* in: ibuf tree root */ 00417 mtr_t* mtr) /* in: mtr */ 00418 { 00419 ulint old_size; 00420 00421 #ifdef UNIV_SYNC_DEBUG 00422 ut_ad(mutex_own(&ibuf_mutex)); 00423 #endif /* UNIV_SYNC_DEBUG */ 00424 00425 old_size = data->size; 00426 00427 data->free_list_len = flst_get_len(root + PAGE_HEADER 00428 + PAGE_BTR_IBUF_FREE_LIST, mtr); 00429 00430 data->height = 1 + btr_page_get_level(root, mtr); 00431 00432 data->size = data->seg_size - (1 + data->free_list_len); 00433 /* the '1 +' is the ibuf header page */ 00434 ut_ad(data->size < data->seg_size); 00435 00436 if (page_get_n_recs(root) == 0) { 00437 00438 data->empty = TRUE; 00439 } else { 00440 data->empty = FALSE; 00441 } 00442 00443 ut_ad(ibuf->size + data->size >= old_size); 00444 00445 ibuf->size = ibuf->size + data->size - old_size; 00446 00447 /* fprintf(stderr, "ibuf size %lu, space ibuf size %lu\n", ibuf->size, 00448 data->size); */ 00449 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool ibuf_data_too_much_free | ( | ibuf_data_t * | data | ) |
Definition at line 1601 of file ibuf0ibuf.c.
References FALSE, ibuf_mutex, TRUE, and ut_ad.
Referenced by ibuf_free_excess_pages(), and ibuf_remove_free_page().
01603 : TRUE if enough free pages in list */ 01604 ibuf_data_t* data) /* in: ibuf data for the space */ 01605 { 01606 #ifdef UNIV_SYNC_DEBUG 01607 ut_ad(mutex_own(&ibuf_mutex)); 01608 #endif /* UNIV_SYNC_DEBUG */ 01609 01610 if (data->free_list_len >= 3 + data->size / 2 + 3 * data->height) { 01611 01612 return(TRUE); 01613 } 01614 01615 return(FALSE); 01616 }
Here is the caller graph for this function:

| void ibuf_delete_for_discarded_space | ( | ulint | space | ) |
Definition at line 3321 of file ibuf0ibuf.c.
References BTR_MODIFY_LEAF, btr_pcur_close(), btr_pcur_get_rec(), btr_pcur_is_after_last_in_tree(), btr_pcur_is_after_last_on_page(), btr_pcur_is_on_user_rec(), btr_pcur_open_on_user_rec(), fil_space_get_ibuf_data(), ibuf_delete_rec(), ibuf_enter(), ibuf_exit(), ibuf_mutex, ibuf_new_search_tuple_build(), ibuf_rec_get_page_no(), ibuf_rec_get_space(), mem_heap_create, mem_heap_free, mtr_commit(), mtr_start(), mutex_enter, mutex_exit(), PAGE_CUR_GE, and ut_ad.
Referenced by fil_discard_tablespace(), and row_import_tablespace_for_mysql().
03323 : space id */ 03324 { 03325 mem_heap_t* heap; 03326 btr_pcur_t pcur; 03327 dtuple_t* search_tuple; 03328 rec_t* ibuf_rec; 03329 ulint page_no; 03330 ibool closed; 03331 ibuf_data_t* ibuf_data; 03332 ulint n_inserts; 03333 mtr_t mtr; 03334 03335 /* Currently the insert buffer of space 0 takes care of inserts to all 03336 tablespaces */ 03337 03338 ibuf_data = fil_space_get_ibuf_data(0); 03339 03340 heap = mem_heap_create(512); 03341 03342 /* Use page number 0 to build the search tuple so that we get the 03343 cursor positioned at the first entry for this space id */ 03344 03345 search_tuple = ibuf_new_search_tuple_build(space, 0, heap); 03346 03347 n_inserts = 0; 03348 loop: 03349 ibuf_enter(); 03350 03351 mtr_start(&mtr); 03352 03353 /* Position pcur in the insert buffer at the first entry for the 03354 space */ 03355 btr_pcur_open_on_user_rec(ibuf_data->index, search_tuple, PAGE_CUR_GE, 03356 BTR_MODIFY_LEAF, &pcur, &mtr); 03357 if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { 03358 ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr)); 03359 03360 goto leave_loop; 03361 } 03362 03363 for (;;) { 03364 ut_ad(btr_pcur_is_on_user_rec(&pcur, &mtr)); 03365 03366 ibuf_rec = btr_pcur_get_rec(&pcur); 03367 03368 /* Check if the entry is for this space */ 03369 if (ibuf_rec_get_space(ibuf_rec) != space) { 03370 03371 goto leave_loop; 03372 } 03373 03374 page_no = ibuf_rec_get_page_no(ibuf_rec); 03375 03376 n_inserts++; 03377 03378 /* Delete the record from ibuf */ 03379 closed = ibuf_delete_rec(space, page_no, &pcur, search_tuple, 03380 &mtr); 03381 if (closed) { 03382 /* Deletion was pessimistic and mtr was committed: 03383 we start from the beginning again */ 03384 03385 ibuf_exit(); 03386 03387 goto loop; 03388 } 03389 03390 if (btr_pcur_is_after_last_on_page(&pcur, &mtr)) { 03391 mtr_commit(&mtr); 03392 btr_pcur_close(&pcur); 03393 03394 ibuf_exit(); 03395 03396 goto loop; 03397 } 03398 } 03399 03400 leave_loop: 03401 mtr_commit(&mtr); 03402 btr_pcur_close(&pcur); 03403 03404 /* Protect our statistics keeping from race conditions */ 03405 mutex_enter(&ibuf_mutex); 03406 03407 ibuf_data->n_merges++; 03408 ibuf_data->n_merged_recs += n_inserts; 03409 03410 mutex_exit(&ibuf_mutex); 03411 /* 03412 fprintf(stderr, 03413 "InnoDB: Discarded %lu ibuf entries for space %lu\n", 03414 (ulong) n_inserts, (ulong) space); 03415 */ 03416 ibuf_exit(); 03417 03418 mem_heap_free(heap); 03419 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool ibuf_delete_rec | ( | ulint | space, | |
| ulint | page_no, | |||
| btr_pcur_t * | pcur, | |||
| dtuple_t * | search_tuple, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 2916 of file ibuf0ibuf.c.
References btr_cur_optimistic_delete(), btr_cur_pessimistic_delete(), BTR_MODIFY_TREE, btr_pcur_close(), btr_pcur_commit_specify_mtr(), btr_pcur_get_btr_cur(), btr_pcur_get_rec(), btr_pcur_restore_position(), btr_pcur_store_position(), btr_validate_tree(), DB_SUCCESS, dtuple_print(), err, FALSE, fil_space_get_ibuf_data(), ibuf_data_sizes_update(), ibuf_inside(), ibuf_mutex, ibuf_tree_root_get(), ibuf_validate_low(), mtr_start(), mutex_enter, mutex_exit(), NULL, btr_pcur_struct::old_rec, page_rec_get_next(), page_t, rec_print_old(), TRUE, ut_a, ut_ad, ut_error, and UT_NOT_USED.
Referenced by ibuf_delete_for_discarded_space(), and ibuf_merge_or_delete_for_page().
02918 : TRUE if mtr was committed and pcur 02919 closed in this operation */ 02920 ulint space, /* in: space id */ 02921 ulint page_no,/* in: index page number where the record 02922 should belong */ 02923 btr_pcur_t* pcur, /* in: pcur positioned on the record to 02924 delete, having latch mode BTR_MODIFY_LEAF */ 02925 dtuple_t* search_tuple, 02926 /* in: search tuple for entries of page_no */ 02927 mtr_t* mtr) /* in: mtr */ 02928 { 02929 ibool success; 02930 ibuf_data_t* ibuf_data; 02931 page_t* root; 02932 ulint err; 02933 02934 ut_ad(ibuf_inside()); 02935 02936 success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr); 02937 02938 if (success) { 02939 #ifdef UNIV_IBUF_DEBUG 02940 printf( 02941 "Decrementing ibuf count of space %lu page %lu\n" 02942 "from %lu by 1\n", space, page_no, ibuf_count_get(space, page_no)); 02943 ibuf_count_set(space, page_no, 02944 ibuf_count_get(space, page_no) - 1); 02945 #endif 02946 return(FALSE); 02947 } 02948 02949 /* We have to resort to a pessimistic delete from ibuf */ 02950 btr_pcur_store_position(pcur, mtr); 02951 02952 btr_pcur_commit_specify_mtr(pcur, mtr); 02953 02954 /* Currently the insert buffer of space 0 takes care of inserts to all 02955 tablespaces */ 02956 02957 ibuf_data = fil_space_get_ibuf_data(0); 02958 02959 mutex_enter(&ibuf_mutex); 02960 02961 mtr_start(mtr); 02962 02963 success = btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr); 02964 02965 if (!success) { 02966 fprintf(stderr, 02967 "InnoDB: ERROR: Submit the output to http://bugs.mysql.com\n" 02968 "InnoDB: ibuf cursor restoration fails!\n" 02969 "InnoDB: ibuf record inserted to page %lu\n", (ulong) page_no); 02970 fflush(stderr); 02971 02972 rec_print_old(stderr, btr_pcur_get_rec(pcur)); 02973 rec_print_old(stderr, pcur->old_rec); 02974 dtuple_print(stderr, search_tuple); 02975 02976 rec_print_old(stderr, 02977 page_rec_get_next(btr_pcur_get_rec(pcur))); 02978 fflush(stderr); 02979 02980 btr_pcur_commit_specify_mtr(pcur, mtr); 02981 02982 fputs("InnoDB: Validating insert buffer tree:\n", stderr); 02983 if (!btr_validate_tree(ibuf_data->index->tree, NULL)) { 02984 ut_error; 02985 } 02986 02987 fprintf(stderr, "InnoDB: ibuf tree ok\n"); 02988 fflush(stderr); 02989 02990 btr_pcur_close(pcur); 02991 02992 mutex_exit(&ibuf_mutex); 02993 02994 return(TRUE); 02995 } 02996 02997 root = ibuf_tree_root_get(ibuf_data, 0, mtr); 02998 02999 btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur), 03000 FALSE, mtr); 03001 ut_a(err == DB_SUCCESS); 03002 03003 #ifdef UNIV_IBUF_DEBUG 03004 ibuf_count_set(space, page_no, ibuf_count_get(space, page_no) - 1); 03005 #else 03006 UT_NOT_USED(space); 03007 #endif 03008 ibuf_data_sizes_update(ibuf_data, root, mtr); 03009 03010 ut_ad(ibuf_validate_low()); 03011 03012 btr_pcur_commit_specify_mtr(pcur, mtr); 03013 03014 btr_pcur_close(pcur); 03015 03016 mutex_exit(&ibuf_mutex); 03017 03018 return(TRUE); 03019 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void ibuf_dummy_index_add_col | ( | dict_index_t * | index, | |
| dtype_t * | type, | |||
| ulint | len | |||
| ) | [static] |
Definition at line 1142 of file ibuf0ibuf.c.
References dict_index_add_col(), dict_mem_table_add_col(), dict_table_get_nth_col(), dtype_get_len(), dtype_get_mtype(), dtype_get_prec(), dtype_get_prtype(), and index().
Referenced by ibuf_build_entry_from_ibuf_rec().
01144 : dummy index */ 01145 dtype_t* type, /* in: the data type of the column */ 01146 ulint len) /* in: length of the column */ 01147 { 01148 ulint i = index->table->n_def; 01149 dict_mem_table_add_col(index->table, "DUMMY", 01150 dtype_get_mtype(type), 01151 dtype_get_prtype(type), 01152 dtype_get_len(type), 01153 dtype_get_prec(type)); 01154 dict_index_add_col(index, 01155 dict_table_get_nth_col(index->table, i), len); 01156 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static dict_index_t* ibuf_dummy_index_create | ( | ulint | n, | |
| ibool | comp | |||
| ) | [static] |
Definition at line 1116 of file ibuf0ibuf.c.
References DICT_HDR_SPACE, dict_mem_index_create(), dict_mem_table_create(), DICT_TF_COMPACT, index(), and TRUE.
Referenced by ibuf_build_entry_from_ibuf_rec().
01118 : dummy index */ 01119 ulint n, /* in: number of fields */ 01120 ibool comp) /* in: TRUE=use compact record format */ 01121 { 01122 dict_table_t* table; 01123 dict_index_t* index; 01124 01125 table = dict_mem_table_create("IBUF_DUMMY", 01126 DICT_HDR_SPACE, n, comp ? DICT_TF_COMPACT : 0); 01127 01128 index = dict_mem_index_create("IBUF_DUMMY", "IBUF_DUMMY", 01129 DICT_HDR_SPACE, 0, n); 01130 01131 index->table = table; 01132 01133 /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */ 01134 index->cached = TRUE; 01135 01136 return(index); 01137 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void ibuf_dummy_index_free | ( | dict_index_t * | index | ) | [static] |
Definition at line 1162 of file ibuf0ibuf.c.
References dict_mem_index_free(), dict_mem_table_free(), and index().
Referenced by ibuf_merge_or_delete_for_page(), and ibuf_rec_get_volume().
01164 : dummy index */ 01165 { 01166 dict_table_t* table = index->table; 01167 01168 dict_mem_index_free(index); 01169 dict_mem_table_free(table); 01170 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void ibuf_enter | ( | void | ) |
Definition at line 225 of file ibuf0ibuf.c.
References FALSE, thr_local_get_in_ibuf_field(), TRUE, and ut_ad.
Referenced by ibuf_add_free_page(), ibuf_data_init_for_space(), ibuf_delete_for_discarded_space(), ibuf_insert_low(), ibuf_is_empty(), ibuf_merge_or_delete_for_page(), ibuf_remove_free_page(), and ibuf_update_max_tablespace_id().
00227 { 00228 ibool* ptr; 00229 00230 ptr = thr_local_get_in_ibuf_field(); 00231 00232 ut_ad(*ptr == FALSE); 00233 00234 *ptr = TRUE; 00235 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static dtuple_t* ibuf_entry_build | ( | dtuple_t * | entry, | |
| ibool | comp, | |||
| ulint | space, | |||
| ulint | page_no, | |||
| mem_heap_t * | heap | |||
| ) | [static] |
Definition at line 1365 of file ibuf0ibuf.c.
References buf, DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE, dfield_copy(), dfield_get_type(), dfield_set_data(), dtuple_create(), dtuple_get_n_fields(), dtuple_get_nth_field(), dtuple_set_types_binary(), dtype_new_store_for_order_and_null_size(), mach_write_to_1(), mach_write_to_4(), mem_heap_alloc(), and ut_ad.
Referenced by ibuf_insert_low().
01367 : entry to insert into an ibuf 01368 index tree; NOTE that the original entry 01369 must be kept because we copy pointers to its 01370 fields */ 01371 dtuple_t* entry, /* in: entry for a non-clustered index */ 01372 ibool comp, /* in: flag: TRUE=compact record format */ 01373 ulint space, /* in: space id */ 01374 ulint page_no,/* in: index page number where entry should 01375 be inserted */ 01376 mem_heap_t* heap) /* in: heap into which to build */ 01377 { 01378 dtuple_t* tuple; 01379 dfield_t* field; 01380 dfield_t* entry_field; 01381 ulint n_fields; 01382 byte* buf; 01383 byte* buf2; 01384 ulint i; 01385 01386 /* Starting from 4.1.x, we have to build a tuple whose 01387 (1) first field is the space id, 01388 (2) the second field a single marker byte (0) to tell that this 01389 is a new format record, 01390 (3) the third contains the page number, and 01391 (4) the fourth contains the relevent type information of each data 01392 field; the length of this field % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE is 01393 (a) 0 for b-trees in the old format, and 01394 (b) 1 for b-trees in the compact format, the first byte of the field 01395 being the marker (0); 01396 (5) and the rest of the fields are copied from entry. All fields 01397 in the tuple are ordered like the type binary in our insert buffer 01398 tree. */ 01399 01400 n_fields = dtuple_get_n_fields(entry); 01401 01402 tuple = dtuple_create(heap, n_fields + 4); 01403 01404 /* Store the space id in tuple */ 01405 01406 field = dtuple_get_nth_field(tuple, 0); 01407 01408 buf = mem_heap_alloc(heap, 4); 01409 01410 mach_write_to_4(buf, space); 01411 01412 dfield_set_data(field, buf, 4); 01413 01414 /* Store the marker byte field in tuple */ 01415 01416 field = dtuple_get_nth_field(tuple, 1); 01417 01418 buf = mem_heap_alloc(heap, 1); 01419 01420 /* We set the marker byte zero */ 01421 01422 mach_write_to_1(buf, 0); 01423 01424 dfield_set_data(field, buf, 1); 01425 01426 /* Store the page number in tuple */ 01427 01428 field = dtuple_get_nth_field(tuple, 2); 01429 01430 buf = mem_heap_alloc(heap, 4); 01431 01432 mach_write_to_4(buf, page_no); 01433 01434 dfield_set_data(field, buf, 4); 01435 01436 ut_ad(comp == 0 || comp == 1); 01437 /* Store the type info in buf2, and add the fields from entry to 01438 tuple */ 01439 buf2 = mem_heap_alloc(heap, n_fields 01440 * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 01441 + comp); 01442 if (comp) { 01443 *buf2++ = 0; /* write the compact format indicator */ 01444 } 01445 for (i = 0; i < n_fields; i++) { 01446 /* We add 4 below because we have the 4 extra fields at the 01447 start of an ibuf record */ 01448 01449 field = dtuple_get_nth_field(tuple, i + 4); 01450 entry_field = dtuple_get_nth_field(entry, i); 01451 dfield_copy(field, entry_field); 01452 01453 dtype_new_store_for_order_and_null_size( 01454 buf2 + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE, 01455 dfield_get_type(entry_field)); 01456 } 01457 01458 /* Store the type info in buf2 to field 3 of tuple */ 01459 01460 field = dtuple_get_nth_field(tuple, 3); 01461 01462 if (comp) { 01463 buf2--; 01464 } 01465 01466 dfield_set_data(field, buf2, n_fields 01467 * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 01468 + comp); 01469 /* Set all the types in the new tuple binary */ 01470 01471 dtuple_set_types_binary(tuple, n_fields + 4); 01472 01473 return(tuple); 01474 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void ibuf_exit | ( | void | ) |
Definition at line 242 of file ibuf0ibuf.c.
References FALSE, thr_local_get_in_ibuf_field(), TRUE, and ut_ad.
Referenced by ibuf_add_free_page(), ibuf_data_init_for_space(), ibuf_delete_for_discarded_space(), ibuf_insert_low(), ibuf_is_empty(), ibuf_merge_or_delete_for_page(), ibuf_remove_free_page(), and ibuf_update_max_tablespace_id().
00244 { 00245 ibool* ptr; 00246 00247 ptr = thr_local_get_in_ibuf_field(); 00248 00249 ut_ad(*ptr == TRUE); 00250 00251 *ptr = FALSE; 00252 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 952 of file ibuf0ibuf.c.
References ibuf_bitmap_page(), and IBUF_TREE_ROOT_PAGE_NO.
Referenced by ibuf_merge_or_delete_for_page(), ibuf_page(), and ibuf_page_low().
00954 : TRUE if a fixed address ibuf i/o page */ 00955 ulint space, /* in: space id */ 00956 ulint page_no)/* in: page number */ 00957 { 00958 return((space == 0 && page_no == IBUF_TREE_ROOT_PAGE_NO) 00959 || ibuf_bitmap_page(page_no)); 00960 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void ibuf_free_excess_pages | ( | ulint | space | ) |
Definition at line 1829 of file ibuf0ibuf.c.
References fil_space_get_ibuf_data(), fil_space_get_latch(), ibuf_data_too_much_free(), ibuf_inside(), ibuf_mutex, ibuf_remove_free_page(), mutex_enter, mutex_exit(), NULL, RW_LOCK_EX, rw_lock_get_x_lock_count(), and ut_ad.
Referenced by fseg_alloc_free_page_general(), and fseg_create_general().
01831 : space id */ 01832 { 01833 ibuf_data_t* ibuf_data; 01834 ulint i; 01835 01836 if (space != 0) { 01837 fprintf(stderr, 01838 "InnoDB: Error: calling ibuf_free_excess_pages for space %lu\n", (ulong) space); 01839 return; 01840 } 01841 01842 #ifdef UNIV_SYNC_DEBUG 01843 ut_ad(rw_lock_own(fil_space_get_latch(space), RW_LOCK_EX)); 01844 #endif /* UNIV_SYNC_DEBUG */ 01845 ut_ad(rw_lock_get_x_lock_count(fil_space_get_latch(space)) == 1); 01846 ut_ad(!ibuf_inside()); 01847 01848 /* NOTE: We require that the thread did not own the latch before, 01849 because then we know that we can obey the correct latching order 01850 for ibuf latches */ 01851 01852 ibuf_data = fil_space_get_ibuf_data(space); 01853 01854 if (ibuf_data == NULL) { 01855 /* Not yet initialized */ 01856 01857 #ifdef UNIV_DEBUG 01858 /*fprintf(stderr, 01859 "Ibuf for space %lu not yet initialized\n", space); */ 01860 #endif 01861 01862 return; 01863 } 01864 01865 /* Free at most a few pages at a time, so that we do not delay the 01866 requested service too much */ 01867 01868 for (i = 0; i < 4; i++) { 01869 01870 mutex_enter(&ibuf_mutex); 01871 01872 if (!ibuf_data_too_much_free(ibuf_data)) { 01873 01874 mutex_exit(&ibuf_mutex); 01875 01876 return; 01877 } 01878 01879 mutex_exit(&ibuf_mutex); 01880 01881 ibuf_remove_free_page(space, ibuf_data); 01882 } 01883 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint ibuf_get_merge_page_nos | ( | ibool | contract, | |
| rec_t * | rec, | |||
| ulint * | space_ids, | |||
| ib_longlong * | space_versions, | |||
| ulint * | page_nos, | |||
| ulint * | n_stored | |||
| ) | [static] |
Definition at line 1889 of file ibuf0ibuf.c.
References buf_pool, buf_pool_struct::curr_size, fil_space_get_version(), IBUF_MAX_N_PAGES_MERGED, IBUF_MERGE_AREA, IBUF_MERGE_THRESHOLD, ibuf_rec_get_page_no(), ibuf_rec_get_space(), ibuf_rec_get_volume(), IBUF_TREE_ROOT_PAGE_NO, page_rec_get_next(), page_rec_get_prev(), page_rec_is_infimum(), page_rec_is_supremum(), UNIV_PAGE_SIZE, ut_a, ut_ad, and ut_min().
Referenced by ibuf_insert_low().
01891 : a lower limit for the combined volume 01892 of records which will be merged */ 01893 ibool contract,/* in: TRUE if this function is called to 01894 contract the tree, FALSE if this is called 01895 when a single page becomes full and we look 01896 if it pays to read also nearby pages */ 01897 rec_t* rec, /* in: record from which we read up and down 01898 in the chain of records */ 01899 ulint* space_ids,/* in/out: space id's of the pages */ 01900 ib_longlong* space_versions,/* in/out: tablespace version 01901 timestamps; used to prevent reading in old 01902 pages after DISCARD + IMPORT tablespace */ 01903 ulint* page_nos,/* in/out: buffer for at least 01904 IBUF_MAX_N_PAGES_MERGED many page numbers; 01905 the page numbers are in an ascending order */ 01906 ulint* n_stored)/* out: number of page numbers stored to 01907 page_nos in this function */ 01908 { 01909 ulint prev_page_no; 01910 ulint prev_space_id; 01911 ulint first_page_no; 01912 ulint first_space_id; 01913 ulint rec_page_no; 01914 ulint rec_space_id; 01915 ulint sum_volumes; 01916 ulint volume_for_page; 01917 ulint rec_volume; 01918 ulint limit; 01919 ulint n_pages; 01920 01921 *n_stored = 0; 01922 01923 limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool->curr_size / 4); 01924 01925 if (page_rec_is_supremum(rec)) { 01926 01927 rec = page_rec_get_prev(rec); 01928 } 01929 01930 if (page_rec_is_infimum(rec)) { 01931 01932 rec = page_rec_get_next(rec); 01933 } 01934 01935 if (page_rec_is_supremum(rec)) { 01936 01937 return(0); 01938 } 01939 01940 first_page_no = ibuf_rec_get_page_no(rec); 01941 first_space_id = ibuf_rec_get_space(rec); 01942 n_pages = 0; 01943 prev_page_no = 0; 01944 prev_space_id = 0; 01945 01946 /* Go backwards from the first rec until we reach the border of the 01947 'merge area', or the page start or the limit of storeable pages is 01948 reached */ 01949 01950 while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) { 01951 01952 rec_page_no = ibuf_rec_get_page_no(rec); 01953 rec_space_id = ibuf_rec_get_space(rec); 01954 01955 if (rec_space_id != first_space_id 01956 || rec_page_no / IBUF_MERGE_AREA 01957 != first_page_no / IBUF_MERGE_AREA) { 01958 01959 break; 01960 } 01961 01962 if (rec_page_no != prev_page_no 01963 || rec_space_id != prev_space_id) { 01964 n_pages++; 01965 } 01966 01967 prev_page_no = rec_page_no; 01968 prev_space_id = rec_space_id; 01969 01970 rec = page_rec_get_prev(rec); 01971 } 01972 01973 rec = page_rec_get_next(rec); 01974 01975 /* At the loop start there is no prev page; we mark this with a pair 01976 of space id, page no (0, 0) for which there can never be entries in 01977 the insert buffer */ 01978 01979 prev_page_no = 0; 01980 prev_space_id = 0; 01981 sum_volumes = 0; 01982 volume_for_page = 0; 01983 01984 while (*n_stored < limit) { 01985 if (page_rec_is_supremum(rec)) { 01986 /* When no more records available, mark this with 01987 another 'impossible' pair of space id, page no */ 01988 rec_page_no = 1; 01989 rec_space_id = 0; 01990 } else { 01991 rec_page_no = ibuf_rec_get_page_no(rec); 01992 rec_space_id = ibuf_rec_get_space(rec); 01993 ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO); 01994 } 01995 01996 #ifdef UNIV_IBUF_DEBUG 01997 ut_a(*n_stored < IBUF_MAX_N_PAGES_MERGED); 01998 #endif 01999 if ((rec_space_id != prev_space_id 02000 || rec_page_no != prev_page_no) 02001 && (prev_space_id != 0 || prev_page_no != 0)) { 02002 02003 if ((prev_page_no == first_page_no 02004 && prev_space_id == first_space_id) 02005 || contract 02006 || (volume_for_page > 02007 ((IBUF_MERGE_THRESHOLD - 1) 02008 * 4 * UNIV_PAGE_SIZE 02009 / IBUF_PAGE_SIZE_PER_FREE_SPACE) 02010 / IBUF_MERGE_THRESHOLD)) { 02011 02012 space_ids[*n_stored] = prev_space_id; 02013 space_versions[*n_stored] 02014 = fil_space_get_version( 02015 prev_space_id); 02016 page_nos[*n_stored] = prev_page_no; 02017 02018 (*n_stored)++; 02019 02020 sum_volumes += volume_for_page; 02021 } 02022 02023 if (rec_space_id != first_space_id 02024 || rec_page_no / IBUF_MERGE_AREA 02025 != first_page_no / IBUF_MERGE_AREA) { 02026 02027 break; 02028 } 02029 02030 volume_for_page = 0; 02031 } 02032 02033 if (rec_page_no == 1 && rec_space_id == 0) { 02034 /* Supremum record */ 02035 02036 break; 02037 } 02038 02039 rec_volume = ibuf_rec_get_volume(rec); 02040 02041 volume_for_page += rec_volume; 02042 02043 prev_page_no = rec_page_no; 02044 prev_space_id = rec_space_id; 02045 02046 rec = page_rec_get_next(rec); 02047 } 02048 02049 #ifdef UNIV_IBUF_DEBUG 02050 ut_a(*n_stored <= IBUF_MAX_N_PAGES_MERGED); 02051 #endif 02052 /* fprintf(stderr, "Ibuf merge batch %lu pages %lu volume\n", *n_stored, 02053 sum_volumes); */ 02054 return(sum_volumes); 02055 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint ibuf_get_volume_buffered | ( | btr_pcur_t * | pcur, | |
| ulint | space, | |||
| ulint | page_no, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 2276 of file ibuf0ibuf.c.
References BTR_MODIFY_PREV, BTR_MODIFY_TREE, btr_page_get_next(), btr_page_get_prev(), btr_pcur_get_rec(), buf_frame_align(), buf_frame_get_page_no(), buf_page_get, FIL_NULL, ibuf_rec_get_page_no(), ibuf_rec_get_space(), ibuf_rec_get_volume(), btr_pcur_struct::latch_mode, page_get_infimum_rec(), page_get_supremum_rec(), page_rec_get_next(), page_rec_get_prev(), page_rec_is_infimum(), page_rec_is_supremum(), page_t, RW_X_LATCH, SYNC_TREE_NODE, trx_sys_multiple_tablespace_format, UNIV_PAGE_SIZE, ut_a, and ut_ad.
Referenced by ibuf_insert_low().
02278 : upper limit for the volume of 02279 buffered inserts for the index page, in bytes; 02280 we may also return UNIV_PAGE_SIZE, if the 02281 entries for the index page span on several 02282 pages in the insert buffer */ 02283 btr_pcur_t* pcur, /* in: pcur positioned at a place in an 02284 insert buffer tree where we would insert an 02285 entry for the index page whose number is 02286 page_no, latch mode has to be BTR_MODIFY_PREV 02287 or BTR_MODIFY_TREE */ 02288 ulint space, /* in: space id */ 02289 ulint page_no,/* in: page number of an index page */ 02290 mtr_t* mtr) /* in: mtr */ 02291 { 02292 ulint volume; 02293 rec_t* rec; 02294 page_t* page; 02295 ulint prev_page_no; 02296 page_t* prev_page; 02297 ulint next_page_no; 02298 page_t* next_page; 02299 02300 ut_a(trx_sys_multiple_tablespace_format); 02301 02302 ut_ad((pcur->latch_mode == BTR_MODIFY_PREV) 02303 || (pcur->latch_mode == BTR_MODIFY_TREE)); 02304 02305 /* Count the volume of records earlier in the alphabetical order than 02306 pcur */ 02307 02308 volume = 0; 02309 02310 rec = btr_pcur_get_rec(pcur); 02311 02312 page = buf_frame_align(rec); 02313 02314 if (page_rec_is_supremum(rec)) { 02315 rec = page_rec_get_prev(rec); 02316 } 02317 02318 for (;;) { 02319 if (page_rec_is_infimum(rec)) { 02320 02321 break; 02322 } 02323 02324 if (page_no != ibuf_rec_get_page_no(rec) 02325 || space != ibuf_rec_get_space(rec)) { 02326 02327 goto count_later; 02328 } 02329 02330 volume += ibuf_rec_get_volume(rec); 02331 02332 rec = page_rec_get_prev(rec); 02333 } 02334 02335 /* Look at the previous page */ 02336 02337 prev_page_no = btr_page_get_prev(page, mtr); 02338 02339 if (prev_page_no == FIL_NULL) { 02340 02341 goto count_later; 02342 } 02343 02344 prev_page = buf_page_get(0, prev_page_no, RW_X_LATCH, mtr); 02345 #ifdef UNIV_BTR_DEBUG 02346 ut_a(btr_page_get_next(prev_page, mtr) 02347 == buf_frame_get_page_no(page)); 02348 #endif /* UNIV_BTR_DEBUG */ 02349 02350 #ifdef UNIV_SYNC_DEBUG 02351 buf_page_dbg_add_level(prev_page, SYNC_TREE_NODE); 02352 #endif /* UNIV_SYNC_DEBUG */ 02353 02354 rec = page_get_supremum_rec(prev_page); 02355 rec = page_rec_get_prev(rec); 02356 02357 for (;;) { 02358 if (page_rec_is_infimum(rec)) { 02359 02360 /* We cannot go to yet a previous page, because we 02361 do not have the x-latch on it, and cannot acquire one 02362 because of the latching order: we have to give up */ 02363 02364 return(UNIV_PAGE_SIZE); 02365 } 02366 02367 if (page_no != ibuf_rec_get_page_no(rec) 02368 || space != ibuf_rec_get_space(rec)) { 02369 02370 goto count_later; 02371 } 02372 02373 volume += ibuf_rec_get_volume(rec); 02374 02375 rec = page_rec_get_prev(rec); 02376 } 02377 02378 count_later: 02379 rec = btr_pcur_get_rec(pcur); 02380 02381 if (!page_rec_is_supremum(rec)) { 02382 rec = page_rec_get_next(rec); 02383 } 02384 02385 for (;;) { 02386 if (page_rec_is_supremum(rec)) { 02387 02388 break; 02389 } 02390 02391 if (page_no != ibuf_rec_get_page_no(rec) 02392 || space != ibuf_rec_get_space(rec)) { 02393 02394 return(volume); 02395 } 02396 02397 volume += ibuf_rec_get_volume(rec); 02398 02399 rec = page_rec_get_next(rec); 02400 } 02401 02402 /* Look at the next page */ 02403 02404 next_page_no = btr_page_get_next(page, mtr); 02405 02406 if (next_page_no == FIL_NULL) { 02407 02408 return(volume); 02409 } 02410 02411 next_page = buf_page_get(0, next_page_no, RW_X_LATCH, mtr); 02412 #ifdef UNIV_BTR_DEBUG 02413 ut_a(btr_page_get_prev(next_page, mtr) 02414 == buf_frame_get_page_no(page)); 02415 #endif /* UNIV_BTR_DEBUG */ 02416 02417 #ifdef UNIV_SYNC_DEBUG 02418 buf_page_dbg_add_level(next_page, SYNC_TREE_NODE); 02419 #endif /* UNIV_SYNC_DEBUG */ 02420 02421 rec = page_get_infimum_rec(next_page); 02422 rec = page_rec_get_next(rec); 02423 02424 for (;;) { 02425 if (page_rec_is_supremum(rec)) { 02426 02427 /* We give up */ 02428 02429 return(UNIV_PAGE_SIZE); 02430 } 02431 02432 if (page_no != ibuf_rec_get_page_no(rec) 02433 || space != ibuf_rec_get_space(rec)) { 02434 02435 return(volume); 02436 } 02437 02438 volume += ibuf_rec_get_volume(rec); 02439 02440 rec = page_rec_get_next(rec); 02441 } 02442 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 271 of file ibuf0ibuf.c.
References buf_page_get, FSP_IBUF_HEADER_PAGE_NO, ibuf_inside(), page, page_t, RW_X_LATCH, SYNC_IBUF_HEADER, ut_a, and ut_ad.
Referenced by ibuf_add_free_page(), ibuf_data_init_for_space(), and ibuf_remove_free_page().
00273 : insert buffer header page */ 00274 ulint space, /* in: space id */ 00275 mtr_t* mtr) /* in: mtr */ 00276 { 00277 page_t* page; 00278 00279 ut_a(space == 0); 00280 00281 ut_ad(!ibuf_inside()); 00282 00283 page = buf_page_get(space, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr); 00284 00285 #ifdef UNIV_SYNC_DEBUG 00286 buf_page_dbg_add_level(page, SYNC_IBUF_HEADER); 00287 #endif /* UNIV_SYNC_DEBUG */ 00288 00289 return(page); 00290 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void ibuf_init_at_db_start | ( | void | ) |
Definition at line 365 of file ibuf0ibuf.c.
References buf_pool_get_curr_size(), fil_ibuf_init_at_db_start(), ibuf, ibuf_bitmap_mutex, ibuf_mutex, ibuf_pessimistic_insert_mutex, IBUF_POOL_SIZE_PER_MAX_SIZE, mem_alloc, mutex_create, SYNC_IBUF_BITMAP_MUTEX, SYNC_IBUF_MUTEX, SYNC_IBUF_PESS_INSERT_MUTEX, TRUE, UNIV_PAGE_SIZE, and UT_LIST_INIT.
Referenced by dict_boot().
00367 { 00368 ibuf = mem_alloc(sizeof(ibuf_t)); 00369 00370 /* Note that also a pessimistic delete can sometimes make a B-tree 00371 grow in size, as the references on the upper levels of the tree can 00372 change */ 00373 00374 ibuf->max_size = buf_pool_get_curr_size() / UNIV_PAGE_SIZE 00375 / IBUF_POOL_SIZE_PER_MAX_SIZE; 00376 ibuf->meter = IBUF_THRESHOLD + 1; 00377 00378 UT_LIST_INIT(ibuf->data_list); 00379 00380 ibuf->size = 0; 00381 00382 #ifdef UNIV_IBUF_DEBUG 00383 { 00384 ulint i, j; 00385 00386 for (i = 0; i < IBUF_COUNT_N_SPACES; i++) { 00387 00388 ibuf_counts[i] = mem_alloc(sizeof(ulint) 00389 * IBUF_COUNT_N_PAGES); 00390 for (j = 0; j < IBUF_COUNT_N_PAGES; j++) { 00391 ibuf_count_set(i, j, 0); 00392 } 00393 } 00394 00395 ibuf_counts_inited = TRUE; 00396 } 00397 #endif 00398 mutex_create(&ibuf_pessimistic_insert_mutex, 00399 SYNC_IBUF_PESS_INSERT_MUTEX); 00400 00401 mutex_create(&ibuf_mutex, SYNC_IBUF_MUTEX); 00402 00403 mutex_create(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX); 00404 00405 fil_ibuf_init_at_db_start(); 00406 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool ibuf_insert | ( | dtuple_t * | entry, | |
| dict_index_t * | index, | |||
| ulint | space, | |||
| ulint | page_no, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 2762 of file ibuf0ibuf.c.
References BTR_MODIFY_PREV, BTR_MODIFY_TREE, DB_FAIL, DB_STRONG_FAIL, DB_SUCCESS, DICT_CLUSTERED, dict_table_is_comp(), dtuple_check_typed(), err, FALSE, ibuf_insert_low(), index(), page_get_free_space_of_empty(), rec_get_converted_size(), TRUE, trx_sys_multiple_tablespace_format, ut_a, and ut_ad.
Referenced by btr_cur_search_to_nth_level().
02764 : TRUE if success */ 02765 dtuple_t* entry, /* in: index entry to insert */ 02766 dict_index_t* index, /* in: index where to insert */ 02767 ulint space, /* in: space id where to insert */ 02768 ulint page_no,/* in: page number where to insert */ 02769 que_thr_t* thr) /* in: query thread */ 02770 { 02771 ulint err; 02772 02773 ut_a(trx_sys_multiple_tablespace_format); 02774 ut_ad(dtuple_check_typed(entry)); 02775 02776 ut_a(!(index->type & DICT_CLUSTERED)); 02777 02778 if (rec_get_converted_size(index, entry) 02779 >= page_get_free_space_of_empty( 02780 dict_table_is_comp(index->table)) / 2) { 02781 return(FALSE); 02782 } 02783 02784 err = ibuf_insert_low(BTR_MODIFY_PREV, entry, index, space, page_no, 02785 thr); 02786 if (err == DB_FAIL) { 02787 err = ibuf_insert_low(BTR_MODIFY_TREE, entry, index, space, 02788 page_no, thr); 02789 } 02790 02791 if (err == DB_SUCCESS) { 02792 #ifdef UNIV_IBUF_DEBUG 02793 /* fprintf(stderr, "Ibuf insert for page no %lu of index %s\n", 02794 page_no, index->name); */ 02795 #endif 02796 return(TRUE); 02797 02798 } else { 02799 ut_a(err == DB_STRONG_FAIL); 02800 02801 return(FALSE); 02802 } 02803 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint ibuf_insert_low | ( | ulint | mode, | |
| dtuple_t * | entry, | |||
| dict_index_t * | index, | |||
| ulint | space, | |||
| ulint | page_no, | |||
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 2501 of file ibuf0ibuf.c.
References btr_cur_optimistic_insert(), btr_cur_pessimistic_insert(), BTR_MODIFY_PREV, BTR_MODIFY_TREE, BTR_NO_LOCKING_FLAG, BTR_NO_UNDO_LOG_FLAG, btr_pcur_close(), btr_pcur_get_btr_cur(), btr_pcur_get_rec(), btr_pcur_open(), buf_frame_align(), buf_page_peek(), buf_read_ibuf_merge_pages(), yaSSL::buffered, DB_STRONG_FAIL, DB_SUCCESS, DICT_CLUSTERED, dict_table_is_comp(), dtuple_check_typed(), err, FALSE, fil_space_get_ibuf_data(), ibuf, ibuf_add_free_page(), IBUF_BITMAP_BUFFERED, IBUF_BITMAP_FREE, ibuf_bitmap_get_map_page(), ibuf_bitmap_page_get_bits(), ibuf_bitmap_page_set_bits(), ibuf_contract(), ibuf_contract_after_insert(), IBUF_CONTRACT_DO_NOT_INSERT, ibuf_data_enough_free_for_insert(), ibuf_data_sizes_update(), ibuf_enter(), ibuf_entry_build(), ibuf_exit(), ibuf_get_merge_page_nos(), ibuf_get_volume_buffered(), IBUF_MAX_N_PAGES_MERGED, ibuf_mutex, ibuf_pessimistic_insert_mutex, ibuf_tree_root_get(), ibuf_validate_low(), index(), lock_rec_expl_exist_on_page(), mem_heap_create, mem_heap_free, mtr_commit(), mtr_start(), mutex_enter, mutex_exit(), PAGE_CUR_LE, page_dir_calc_reserved_space(), page_t, page_update_max_trx_id(), rec_get_converted_size(), thr_get_trx(), TRUE, trx_sys_multiple_tablespace_format, ut_a, and ut_ad.
Referenced by ibuf_insert().
02503 : DB_SUCCESS, DB_FAIL, DB_STRONG_FAIL */ 02504 ulint mode, /* in: BTR_MODIFY_PREV or BTR_MODIFY_TREE */ 02505 dtuple_t* entry, /* in: index entry to insert */ 02506 dict_index_t* index, /* in: index where to insert; must not be 02507 unique or clustered */ 02508 ulint space, /* in: space id where to insert */ 02509 ulint page_no,/* in: page number where to insert */ 02510 que_thr_t* thr) /* in: query thread */ 02511 { 02512 big_rec_t* dummy_big_rec; 02513 ulint entry_size; 02514 btr_pcur_t pcur; 02515 btr_cur_t* cursor; 02516 dtuple_t* ibuf_entry; 02517 mem_heap_t* heap; 02518 ulint buffered; 02519 rec_t* ins_rec; 02520 ibool old_bit_value; 02521 page_t* bitmap_page; 02522 ibuf_data_t* ibuf_data; 02523 dict_index_t* ibuf_index; 02524 page_t* root; 02525 ulint err; 02526 ibool do_merge; 02527 ulint space_ids[IBUF_MAX_N_PAGES_MERGED]; 02528 ib_longlong space_versions[IBUF_MAX_N_PAGES_MERGED]; 02529 ulint page_nos[IBUF_MAX_N_PAGES_MERGED]; 02530 ulint n_stored; 02531 ulint bits; 02532 mtr_t mtr; 02533 mtr_t bitmap_mtr; 02534 02535 ut_a(!(index->type & DICT_CLUSTERED)); 02536 ut_ad(dtuple_check_typed(entry)); 02537 02538 ut_a(trx_sys_multiple_tablespace_format); 02539 02540 do_merge = FALSE; 02541 02542 /* Currently the insert buffer of space 0 takes care of inserts to all 02543 tablespaces */ 02544 02545 ibuf_data = fil_space_get_ibuf_data(0); 02546 02547 ibuf_index = ibuf_data->index; 02548 02549 mutex_enter(&ibuf_mutex); 02550 02551 if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_DO_NOT_INSERT) { 02552 /* Insert buffer is now too big, contract it but do not try 02553 to insert */ 02554 02555 mutex_exit(&ibuf_mutex); 02556 02557 #ifdef UNIV_IBUF_DEBUG 02558 fputs("Ibuf too big\n", stderr); 02559 #endif 02560 /* Use synchronous contract (== TRUE) */ 02561 ibuf_contract(TRUE); 02562 02563 return(DB_STRONG_FAIL); 02564 } 02565 02566 mutex_exit(&ibuf_mutex); 02567 02568 if (mode == BTR_MODIFY_TREE) { 02569 mutex_enter(&ibuf_pessimistic_insert_mutex); 02570 02571 ibuf_enter(); 02572 02573 mutex_enter(&ibuf_mutex); 02574 02575 while (!ibuf_data_enough_free_for_insert(ibuf_data)) { 02576 02577 mutex_exit(&ibuf_mutex); 02578 02579 ibuf_exit(); 02580 02581 mutex_exit(&ibuf_pessimistic_insert_mutex); 02582 02583 err = ibuf_add_free_page(0, ibuf_data); 02584 02585 if (err == DB_STRONG_FAIL) { 02586 02587 return(err); 02588 } 02589 02590 mutex_enter(&ibuf_pessimistic_insert_mutex); 02591 02592 ibuf_enter(); 02593 02594 mutex_enter(&ibuf_mutex); 02595 } 02596 } else { 02597 ibuf_enter(); 02598 } 02599 02600 entry_size = rec_get_converted_size(index, entry); 02601 02602 heap = mem_heap_create(512); 02603 02604 /* Build the entry which contains the space id and the page number as 02605 the first fields and the type information for other fields, and which 02606 will be inserted to the insert buffer. */ 02607 02608 ibuf_entry = ibuf_entry_build(entry, dict_table_is_comp(index->table), 02609 space, page_no, heap); 02610 02611 /* Open a cursor to the insert buffer tree to calculate if we can add 02612 the new entry to it without exceeding the free space limit for the 02613 page. */ 02614 02615 mtr_start(&mtr); 02616 02617 btr_pcur_open(ibuf_index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr); 02618 02619 /* Find out the volume of already buffered inserts for the same index 02620 page */ 02621 buffered = ibuf_get_volume_buffered(&pcur, space, page_no, &mtr); 02622 02623 #ifdef UNIV_IBUF_DEBUG 02624 ut_a((buffered == 0) || ibuf_count_get(space, page_no)); 02625 #endif 02626 mtr_start(&bitmap_mtr); 02627 02628 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, &bitmap_mtr); 02629 02630 /* We check if the index page is suitable for buffered entries */ 02631 02632 if (buf_page_peek(space, page_no) 02633 || lock_rec_expl_exist_on_page(space, page_no)) { 02634 err = DB_STRONG_FAIL; 02635 02636 mtr_commit(&bitmap_mtr); 02637 02638 goto function_exit; 02639 } 02640 02641 bits = ibuf_bitmap_page_get_bits(bitmap_page, page_no, 02642 IBUF_BITMAP_FREE, &bitmap_mtr); 02643 02644 if (buffered + entry_size + page_dir_calc_reserved_space(1) 02645 > ibuf_index_page_calc_free_from_bits(bits)) { 02646 mtr_commit(&bitmap_mtr); 02647 02648 /* It may not fit */ 02649 err = DB_STRONG_FAIL; 02650 02651 do_merge = TRUE; 02652 02653 ibuf_get_merge_page_nos(FALSE, btr_pcur_get_rec(&pcur), 02654 space_ids, space_versions, 02655 page_nos, &n_stored); 02656 goto function_exit; 02657 } 02658 02659 /* Set the bitmap bit denoting that the insert buffer contains 02660 buffered entries for this index page, if the bit is not set yet */ 02661 02662 old_bit_value = ibuf_bitmap_page_get_bits(bitmap_page, page_no, 02663 IBUF_BITMAP_BUFFERED, &bitmap_mtr); 02664 if (!old_bit_value) { 02665 ibuf_bitmap_page_set_bits(bitmap_page, page_no, 02666 IBUF_BITMAP_BUFFERED, TRUE, &bitmap_mtr); 02667 } 02668 02669 mtr_commit(&bitmap_mtr); 02670 02671 cursor = btr_pcur_get_btr_cur(&pcur); 02672 02673 if (mode == BTR_MODIFY_PREV) { 02674 err = btr_cur_optimistic_insert(BTR_NO_LOCKING_FLAG, cursor, 02675 ibuf_entry, &ins_rec, 02676 &dummy_big_rec, thr, 02677 &mtr); 02678 if (err == DB_SUCCESS) { 02679 /* Update the page max trx id field */ 02680 page_update_max_trx_id(buf_frame_align(ins_rec), 02681 thr_get_trx(thr)->id); 02682 } 02683 } else { 02684 ut_ad(mode == BTR_MODIFY_TREE); 02685 02686 /* We acquire an x-latch to the root page before the insert, 02687 because a pessimistic insert releases the tree x-latch, 02688 which would cause the x-latching of the root after that to 02689 break the latching order. */ 02690 02691 root = ibuf_tree_root_get(ibuf_data, 0, &mtr); 02692 02693 err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG 02694 | BTR_NO_UNDO_LOG_FLAG, 02695 cursor, 02696 ibuf_entry, &ins_rec, 02697 &dummy_big_rec, thr, 02698 &mtr); 02699 if (err == DB_SUCCESS) { 02700 /* Update the page max trx id field */ 02701 page_update_max_trx_id(buf_frame_align(ins_rec), 02702 thr_get_trx(thr)->id); 02703 } 02704 02705 ibuf_data_sizes_update(ibuf_data, root, &mtr); 02706 } 02707 02708 function_exit: 02709 #ifdef UNIV_IBUF_DEBUG 02710 if (err == DB_SUCCESS) { 02711 printf( 02712 "Incrementing ibuf count of space %lu page %lu\n" 02713 "from %lu by 1\n", space, page_no, ibuf_count_get(space, page_no)); 02714 02715 ibuf_count_set(space, page_no, 02716 ibuf_count_get(space, page_no) + 1); 02717 } 02718 #endif 02719 if (mode == BTR_MODIFY_TREE) { 02720 ut_ad(ibuf_validate_low()); 02721 02722 mutex_exit(&ibuf_mutex); 02723 mutex_exit(&ibuf_pessimistic_insert_mutex); 02724 } 02725 02726 mtr_commit(&mtr); 02727 btr_pcur_close(&pcur); 02728 ibuf_exit(); 02729 02730 mem_heap_free(heap); 02731 02732 mutex_enter(&ibuf_mutex); 02733 02734 if (err == DB_SUCCESS) { 02735 ibuf_data->empty = FALSE; 02736 ibuf_data->n_inserts++; 02737 } 02738 02739 mutex_exit(&ibuf_mutex); 02740 02741 if ((mode == BTR_MODIFY_TREE) && (err == DB_SUCCESS)) { 02742 ibuf_contract_after_insert(entry_size); 02743 } 02744 02745 if (do_merge) { 02746 #ifdef UNIV_IBUF_DEBUG 02747 ut_a(n_stored <= IBUF_MAX_N_PAGES_MERGED); 02748 #endif 02749 buf_read_ibuf_merge_pages(FALSE, space_ids, space_versions, 02750 page_nos, n_stored); 02751 } 02752 02753 return(err); 02754 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void ibuf_insert_to_index_page | ( | dtuple_t * | entry, | |
| page_t * | page, | |||
| dict_index_t * | index, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 2810 of file ibuf0ibuf.c.
References btr_cur_del_unmark_for_ibuf(), btr_page_reorganize(), buf_frame_get_page_no(), buf_frame_get_space_id(), buf_page_print(), dict_table_is_comp(), dtuple_check_typed(), dtuple_get_n_fields(), dtuple_print(), dump, IBUF_BITMAP_FREE, ibuf_bitmap_get_map_page(), ibuf_bitmap_page_get_bits(), ibuf_inside(), index(), NULL, page_cur_get_rec(), PAGE_CUR_LE, page_cur_search(), page_cur_tuple_insert(), page_get_infimum_rec(), page_get_max_insert_size(), page_is_comp(), page_rec_get_next(), page_t, rec_get_converted_size(), rec_get_n_fields(), ut_ad, and ut_print_timestamp().
Referenced by ibuf_merge_or_delete_for_page().
02812 : buffered entry to insert */ 02813 page_t* page, /* in: index page where the buffered entry 02814 should be placed */ 02815 dict_index_t* index, /* in: record descriptor */ 02816 mtr_t* mtr) /* in: mtr */ 02817 { 02818 page_cur_t page_cur; 02819 ulint low_match; 02820 rec_t* rec; 02821 page_t* bitmap_page; 02822 ulint old_bits; 02823 02824 ut_ad(ibuf_inside()); 02825 ut_ad(dtuple_check_typed(entry)); 02826 02827 if (UNIV_UNLIKELY(dict_table_is_comp(index->table) 02828 != (ibool)!!page_is_comp(page))) { 02829 fputs( 02830 "InnoDB: Trying to insert a record from the insert buffer to an index page\n" 02831 "InnoDB: but the 'compact' flag does not match!\n", stderr); 02832 goto dump; 02833 } 02834 02835 rec = page_rec_get_next(page_get_infimum_rec(page)); 02836 02837 if (UNIV_UNLIKELY(rec_get_n_fields(rec, index) 02838 != dtuple_get_n_fields(entry))) { 02839 fputs( 02840 "InnoDB: Trying to insert a record from the insert buffer to an index page\n" 02841 "InnoDB: but the number of fields does not match!\n", stderr); 02842 dump: 02843 buf_page_print(page); 02844 02845 dtuple_print(stderr, entry); 02846 02847 fputs( 02848 "InnoDB: The table where where this index record belongs\n" 02849 "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n" 02850 "InnoDB: your tables.\n" 02851 "InnoDB: Send a detailed bug report to mysql@lists.mysql.com!\n", stderr); 02852 02853 return; 02854 } 02855 02856 low_match = page_cur_search(page, index, entry, 02857 PAGE_CUR_LE, &page_cur); 02858 02859 if (low_match == dtuple_get_n_fields(entry)) { 02860 rec = page_cur_get_rec(&page_cur); 02861 02862 btr_cur_del_unmark_for_ibuf(rec, mtr); 02863 } else { 02864 rec = page_cur_tuple_insert(&page_cur, entry, index, mtr); 02865 02866 if (rec == NULL) { 02867 /* If the record did not fit, reorganize */ 02868 02869 btr_page_reorganize(page, index, mtr); 02870 02871 page_cur_search(page, index, entry, 02872 PAGE_CUR_LE, &page_cur); 02873 02874 /* This time the record must fit */ 02875 if (UNIV_UNLIKELY(!page_cur_tuple_insert( 02876 &page_cur, entry, index, mtr))) { 02877 02878 ut_print_timestamp(stderr); 02879 02880 fprintf(stderr, 02881 "InnoDB: Error: Insert buffer insert fails; page free %lu, dtuple size %lu\n", 02882 (ulong) page_get_max_insert_size(page, 1), 02883 (ulong) rec_get_converted_size(index, entry)); 02884 fputs("InnoDB: Cannot insert index record ", 02885 stderr); 02886 dtuple_print(stderr, entry); 02887 fputs( 02888 "\nInnoDB: The table where where this index record belongs\n" 02889 "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n" 02890 "InnoDB: that table.\n", stderr); 02891 02892 bitmap_page = ibuf_bitmap_get_map_page( 02893 buf_frame_get_space_id(page), 02894 buf_frame_get_page_no(page), 02895 mtr); 02896 old_bits = ibuf_bitmap_page_get_bits( 02897 bitmap_page, 02898 buf_frame_get_page_no(page), 02899 IBUF_BITMAP_FREE, mtr); 02900 02901 fprintf(stderr, "Bitmap bits %lu\n", (ulong) old_bits); 02902 02903 fputs( 02904 "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); 02905 } 02906 } 02907 } 02908 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool ibuf_inside | ( | void | ) |
Definition at line 259 of file ibuf0ibuf.c.
References thr_local_get_in_ibuf_field().
Referenced by btr_cur_search_to_nth_level(), buf_page_get_gen(), buf_page_get_known_nowait(), buf_page_init_for_read(), buf_page_optimistic_get_func(), buf_read_ibuf_merge_pages(), fil_io(), ibuf_contract_ext(), ibuf_delete_rec(), ibuf_free_excess_pages(), ibuf_header_page_get(), ibuf_insert_to_index_page(), ibuf_rec_get_page_no(), ibuf_rec_get_space(), ibuf_rec_get_volume(), and ibuf_tree_root_get().
00261 : TRUE if inside an insert buffer routine: for instance, 00262 a read-ahead of non-ibuf pages is then forbidden */ 00263 { 00264 return(*thr_local_get_in_ibuf_field()); 00265 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool ibuf_is_empty | ( | void | ) |
Definition at line 3456 of file ibuf0ibuf.c.
References data, FALSE, ibuf, ibuf_enter(), ibuf_exit(), ibuf_mutex, ibuf_tree_root_get(), mtr_commit(), mtr_start(), mutex_enter, mutex_exit(), page_get_n_recs(), page_t, TRUE, ut_a, and UT_LIST_GET_FIRST.
Referenced by innobase_start_or_create_for_mysql().
03458 : TRUE if empty */ 03459 { 03460 ibuf_data_t* data; 03461 ibool is_empty; 03462 page_t* root; 03463 mtr_t mtr; 03464 03465 ibuf_enter(); 03466 03467 mutex_enter(&ibuf_mutex); 03468 03469 data = UT_LIST_GET_FIRST(ibuf->data_list); 03470 03471 mtr_start(&mtr); 03472 03473 root = ibuf_tree_root_get(data, 0, &mtr); 03474 03475 if (page_get_n_recs(root) == 0) { 03476 03477 is_empty = TRUE; 03478 03479 if (data->empty == FALSE) { 03480 fprintf(stderr, 03481 "InnoDB: Warning: insert buffer tree is empty but the data struct does not\n" 03482 "InnoDB: know it. This condition is legal if the master thread has not yet\n" 03483 "InnoDB: run to completion.\n"); 03484 } 03485 } else { 03486 ut_a(data->empty == FALSE); 03487 03488 is_empty = FALSE; 03489 } 03490 03491 mtr_commit(&mtr); 03492 03493 ut_a(data->space == 0); 03494 03495 mutex_exit(&ibuf_mutex); 03496 03497 ibuf_exit(); 03498 03499 return(is_empty); 03500 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void ibuf_merge_or_delete_for_page | ( | page_t * | page, | |
| ulint | space, | |||
| ulint | page_no, | |||
| ibool | update_ibuf_bitmap | |||
| ) |
Definition at line 3030 of file ibuf0ibuf.c.
References yaSSL::block, BTR_MODIFY_LEAF, btr_pcur_close(), btr_pcur_get_rec(), btr_pcur_is_after_last_in_tree(), btr_pcur_is_after_last_on_page(), btr_pcur_is_on_user_rec(), btr_pcur_open_on_user_rec(), buf_block_align(), buf_frame_align(), BUF_KEEP_OLD, buf_page_get_known_nowait(), buf_page_print(), FALSE, fil_decr_pending_ibuf_merges(), fil_inc_pending_ibuf_merges(), fil_page_get_type(), FIL_PAGE_INDEX, fil_space_get_ibuf_data(), fsp_descr_page(), IBUF_BITMAP_BUFFERED, IBUF_BITMAP_FREE, ibuf_bitmap_get_map_page(), ibuf_bitmap_page_get_bits(), ibuf_bitmap_page_set_bits(), ibuf_build_entry_from_ibuf_rec(), ibuf_delete_rec(), ibuf_dummy_index_free(), ibuf_enter(), ibuf_exit(), ibuf_fixed_addr_page(), ibuf_insert_to_index_page(), ibuf_mutex, ibuf_new_search_tuple_build(), ibuf_rec_get_page_no(), ibuf_rec_get_space(), ibuf_search_tuple_build(), mem_heap_create, mem_heap_free, mtr_commit(), mtr_start(), mutex_enter, mutex_exit(), NULL, PAGE_CUR_GE, page_dir_calc_reserved_space(), page_get_max_trx_id(), page_header_reset_last_insert(), page_t, page_update_max_trx_id(), rec_get_converted_size(), rec_print_old(), rw_lock_x_lock_move_ownership(), RW_X_LATCH, SRV_FORCE_NO_IBUF_MERGE, srv_force_recovery, SYNC_TREE_NODE, TRUE, trx_doublewrite_must_reset_space_ids, trx_sys_hdr_page(), trx_sys_multiple_tablespace_format, UNIV_PAGE_SIZE, ut_a, ut_ad, and ut_print_timestamp().
Referenced by buf_page_create(), buf_page_io_complete(), and buf_read_ibuf_merge_pages().
03032 : if page has been read from disk, pointer to 03033 the page x-latched, else NULL */ 03034 ulint space, /* in: space id of the index page */ 03035 ulint page_no,/* in: page number of the index page */ 03036 ibool update_ibuf_bitmap)/* in: normally this is set to TRUE, but if 03037 we have deleted or are deleting the tablespace, then we 03038 naturally do not want to update a non-existent bitmap 03039 page */ 03040 { 03041 mem_heap_t* heap; 03042 btr_pcur_t pcur; 03043 dtuple_t* entry; 03044 dtuple_t* search_tuple; 03045 rec_t* ibuf_rec; 03046 buf_block_t* block; 03047 page_t* bitmap_page; 03048 ibuf_data_t* ibuf_data; 03049 ulint n_inserts; 03050 #ifdef UNIV_IBUF_DEBUG 03051 ulint volume; 03052 #endif 03053 ibool tablespace_being_deleted = FALSE; 03054 ibool corruption_noticed = FALSE; 03055 mtr_t mtr; 03056 03057 if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { 03058 03059 return; 03060 } 03061 03062 #ifdef UNIV_LOG_DEBUG 03063 if (space % 2 != 0) { 03064 03065 fputs("No ibuf operation in a replicate space\n", stderr); 03066 03067 return; 03068 } 03069 #endif 03070 if (ibuf_fixed_addr_page(space, page_no) || fsp_descr_page(page_no) 03071 || trx_sys_hdr_page(space, page_no)) { 03072 return; 03073 } 03074 03075 if (update_ibuf_bitmap) { 03076 /* If the following returns FALSE, we get the counter 03077 incremented, and must decrement it when we leave this 03078 function. When the counter is > 0, that prevents tablespace 03079 from being dropped. */ 03080 03081 tablespace_being_deleted = fil_inc_pending_ibuf_merges(space); 03082 03083 if (tablespace_being_deleted) { 03084 /* Do not try to read the bitmap page from space; 03085 just delete the ibuf records for the page */ 03086 03087 page = NULL; 03088 update_ibuf_bitmap = FALSE; 03089 } 03090 } 03091 03092 if (update_ibuf_bitmap) { 03093 mtr_start(&mtr); 03094 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, &mtr); 03095 03096 if (!ibuf_bitmap_page_get_bits(bitmap_page, page_no, 03097 IBUF_BITMAP_BUFFERED, &mtr)) { 03098 /* No inserts buffered for this page */ 03099 mtr_commit(&mtr); 03100 03101 if (!tablespace_being_deleted) { 03102 fil_decr_pending_ibuf_merges(space); 03103 } 03104 03105 return; 03106 } 03107 mtr_commit(&mtr); 03108 } 03109 03110 /* Currently the insert buffer of space 0 takes care of inserts to all 03111 tablespaces */ 03112 03113 ibuf_data = fil_space_get_ibuf_data(0); 03114 03115 ibuf_enter(); 03116 03117 heap = mem_heap_create(512); 03118 03119 if (!trx_sys_multiple_tablespace_format) { 03120 ut_a(trx_doublewrite_must_reset_space_ids); 03121 search_tuple = ibuf_search_tuple_build(space, page_no, heap); 03122 } else { 03123 search_tuple = ibuf_new_search_tuple_build(space, page_no, 03124 heap); 03125 } 03126 03127 if (page) { 03128 /* Move the ownership of the x-latch on the page to this OS 03129 thread, so that we can acquire a second x-latch on it. This 03130 is needed for the insert operations to the index page to pass 03131 the debug checks. */ 03132 03133 block = buf_block_align(page); 03134 rw_lock_x_lock_move_ownership(&(block->lock)); 03135 03136 if (fil_page_get_type(page) != FIL_PAGE_INDEX) { 03137 03138 corruption_noticed = TRUE; 03139 03140 ut_print_timestamp(stderr); 03141 03142 mtr_start(&mtr); 03143 03144 fputs(" InnoDB: Dump of the ibuf bitmap page:\n", 03145 stderr); 03146 03147 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, 03148 &mtr); 03149 buf_page_print(bitmap_page); 03150 03151 mtr_commit(&mtr); 03152 03153 fputs("\nInnoDB: Dump of the page:\n", stderr); 03154 03155 buf_page_print(page); 03156 03157 fprintf(stderr, 03158 "InnoDB: Error: corruption in the tablespace. Bitmap shows insert\n" 03159 "InnoDB: buffer records to page n:o %lu though the page\n" 03160 "InnoDB: type is %lu, which is not an index page!\n" 03161 "InnoDB: We try to resolve the problem by skipping the insert buffer\n" 03162 "InnoDB: merge for this page. Please run CHECK TABLE on your tables\n" 03163 "InnoDB: to determine if they are corrupt after this.\n\n" 03164 "InnoDB: Please submit a detailed bug report to http://bugs.mysql.com\n\n", 03165 (ulong) page_no, 03166 (ulong) fil_page_get_type(page)); 03167 } 03168 } 03169 03170 n_inserts = 0; 03171 #ifdef UNIV_IBUF_DEBUG 03172 volume = 0; 03173 #endif 03174 loop: 03175 mtr_start(&mtr); 03176 03177 if (page) { 03178 ibool success = buf_page_get_known_nowait(RW_X_LATCH, page, 03179 BUF_KEEP_OLD, 03180 __FILE__, __LINE__, 03181 &mtr); 03182 ut_a(success); 03183 #ifdef UNIV_SYNC_DEBUG 03184 buf_page_dbg_add_level(page, SYNC_TREE_NODE); 03185 #endif /* UNIV_SYNC_DEBUG */ 03186 } 03187 03188 /* Position pcur in the insert buffer at the first entry for this 03189 index page */ 03190 btr_pcur_open_on_user_rec(ibuf_data->index, search_tuple, PAGE_CUR_GE, 03191 BTR_MODIFY_LEAF, &pcur, &mtr); 03192 if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { 03193 ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr)); 03194 03195 goto reset_bit; 03196 } 03197 03198 for (;;) { 03199 ut_ad(btr_pcur_is_on_user_rec(&pcur, &mtr)); 03200 03201 ibuf_rec = btr_pcur_get_rec(&pcur); 03202 03203 /* Check if the entry is for this index page */ 03204 if (ibuf_rec_get_page_no(ibuf_rec) != page_no 03205 || ibuf_rec_get_space(ibuf_rec) != space) { 03206 if (page) { 03207 page_header_reset_last_insert(page, &mtr); 03208 } 03209 goto reset_bit; 03210 } 03211 03212 if (corruption_noticed) { 03213 fputs("InnoDB: Discarding record\n ", stderr); 03214 rec_print_old(stderr, ibuf_rec); 03215 fputs("\n from the insert buffer!\n\n", stderr); 03216 } else if (page) { 03217 /* Now we have at pcur a record which should be 03218 inserted to the index page; NOTE that the call below 03219 copies pointers to fields in ibuf_rec, and we must 03220 keep the latch to the ibuf_rec page until the 03221 insertion is finished! */ 03222 dict_index_t* dummy_index; 03223 dulint max_trx_id = page_get_max_trx_id( 03224 buf_frame_align(ibuf_rec)); 03225 page_update_max_trx_id(page, max_trx_id); 03226 03227 entry = ibuf_build_entry_from_ibuf_rec(ibuf_rec, 03228 heap, &dummy_index); 03229 #ifdef UNIV_IBUF_DEBUG 03230 volume += rec_get_converted_size(dummy_index, entry) 03231 + page_dir_calc_reserved_space(1); 03232 ut_a(volume <= 4 * UNIV_PAGE_SIZE 03233 / IBUF_PAGE_SIZE_PER_FREE_SPACE); 03234 #endif 03235 ibuf_insert_to_index_page(entry, page, 03236 dummy_index, &mtr); 03237 ibuf_dummy_index_free(dummy_index); 03238 } 03239 03240 n_inserts++; 03241 03242 /* Delete the record from ibuf */ 03243 if (ibuf_delete_rec(space, page_no, &pcur, search_tuple, 03244 &mtr)) { 03245 /* Deletion was pessimistic and mtr was committed: 03246 we start from the beginning again */ 03247 03248 goto loop; 03249 } 03250 03251 if (btr_pcur_is_after_last_on_page(&pcur, &mtr)) { 03252 mtr_commit(&mtr); 03253 btr_pcur_close(&pcur); 03254 03255 goto loop; 03256 } 03257 } 03258 03259 reset_bit: 03260 #ifdef UNIV_IBUF_DEBUG 03261 if (ibuf_count_get(space, page_no) > 0) { 03262 /* btr_print_tree(ibuf_data->index->tree, 100); 03263 ibuf_print(); */ 03264 } 03265 #endif 03266 if (update_ibuf_bitmap) { 03267 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, &mtr); 03268 ibuf_bitmap_page_set_bits(bitmap_page, page_no, 03269 IBUF_BITMAP_BUFFERED, FALSE, &mtr); 03270 if (page) { 03271 ulint old_bits = ibuf_bitmap_page_get_bits(bitmap_page, 03272 page_no, IBUF_BITMAP_FREE, &mtr); 03273 ulint new_bits = ibuf_index_page_calc_free(page); 03274 #ifdef UNIV_IBUF_DEBUG 03275 /* fprintf(stderr, "Old bits %lu new bits %lu max size %lu\n", 03276 old_bits, new_bits, 03277 page_get_max_insert_size_after_reorganize(page, 1)); */ 03278 #endif 03279 if (old_bits != new_bits) { 03280 ibuf_bitmap_page_set_bits(bitmap_page, page_no, 03281 IBUF_BITMAP_FREE, 03282 new_bits, &mtr); 03283 } 03284 } 03285 } 03286 #ifdef UNIV_IBUF_DEBUG 03287 /* fprintf(stderr, 03288 "Ibuf merge %lu records volume %lu to page no %lu\n", 03289 n_inserts, volume, page_no); */ 03290 #endif 03291 mtr_commit(&mtr); 03292 btr_pcur_close(&pcur); 03293 mem_heap_free(heap); 03294 03295 /* Protect our statistics keeping from race conditions */ 03296 mutex_enter(&ibuf_mutex); 03297 03298 ibuf_data->n_merges++; 03299 ibuf_data->n_merged_recs += n_inserts; 03300 03301 mutex_exit(&ibuf_mutex); 03302 03303 if (update_ibuf_bitmap && !tablespace_being_deleted) { 03304 03305 fil_decr_pending_ibuf_merges(space); 03306 } 03307 03308 ibuf_exit(); 03309 #ifdef UNIV_IBUF_DEBUG 03310 ut_a(ibuf_count_get(space, page_no) == 0); 03311 #endif 03312 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static dtuple_t* ibuf_new_search_tuple_build | ( | ulint | space, | |
| ulint | page_no, | |||
| mem_heap_t * | heap | |||
| ) | [static] |
Definition at line 1518 of file ibuf0ibuf.c.
References buf, dfield_set_data(), dtuple_create(), dtuple_get_nth_field(), dtuple_set_types_binary(), mach_write_to_1(), mach_write_to_4(), mem_heap_alloc(), trx_sys_multiple_tablespace_format, and ut_a.
Referenced by ibuf_delete_for_discarded_space(), and ibuf_merge_or_delete_for_page().
01520 : search tuple */ 01521 ulint space, /* in: space id */ 01522 ulint page_no,/* in: index page number */ 01523 mem_heap_t* heap) /* in: heap into which to build */ 01524 { 01525 dtuple_t* tuple; 01526 dfield_t* field; 01527 byte* buf; 01528 01529 ut_a(trx_sys_multiple_tablespace_format); 01530 01531 tuple = dtuple_create(heap, 3); 01532 01533 /* Store the space id in tuple */ 01534 01535 field = dtuple_get_nth_field(tuple, 0); 01536 01537 buf = mem_heap_alloc(heap, 4); 01538 01539 mach_write_to_4(buf, space); 01540 01541 dfield_set_data(field, buf, 4); 01542 01543 /* Store the new format record marker byte */ 01544 01545 field = dtuple_get_nth_field(tuple, 1); 01546 01547 buf = mem_heap_alloc(heap, 1); 01548 01549 mach_write_to_1(buf, 0); 01550 01551 dfield_set_data(field, buf, 1); 01552 01553 /* Store the page number in tuple */ 01554 01555 field = dtuple_get_nth_field(tuple, 2); 01556 01557 buf = mem_heap_alloc(heap, 4); 01558 01559 mach_write_to_4(buf, page_no); 01560 01561 dfield_set_data(field, buf, 4); 01562 01563 dtuple_set_types_binary(tuple, 3); 01564 01565 return(tuple); 01566 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 966 of file ibuf0ibuf.c.
References FALSE, fil_space_get_type(), FIL_TABLESPACE, ibuf_bitmap_get_map_page(), IBUF_BITMAP_IBUF, ibuf_bitmap_page_get_bits(), ibuf_fixed_addr_page(), mtr_commit(), mtr_start(), page_t, recv_no_ibuf_operations, TRUE, and ut_ad.
Referenced by buf_page_get_gen(), buf_page_optimistic_get_func(), fil_io(), and fsp_fill_free_list().
00968 : TRUE if level 2 or level 3 page */ 00969 ulint space, /* in: space id */ 00970 ulint page_no)/* in: page number */ 00971 { 00972 page_t* bitmap_page; 00973 mtr_t mtr; 00974 ibool ret; 00975 00976 if (recv_no_ibuf_operations) { 00977 /* Recovery is running: no ibuf operations should be 00978 performed */ 00979 00980 return(FALSE); 00981 } 00982 00983 if (ibuf_fixed_addr_page(space, page_no)) { 00984 00985 return(TRUE); 00986 } 00987 00988 if (space != 0) { 00989 /* Currently we only have an ibuf tree in space 0 */ 00990 00991 return(FALSE); 00992 } 00993 00994 ut_ad(fil_space_get_type(space) == FIL_TABLESPACE); 00995 00996 mtr_start(&mtr); 00997 00998 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, &mtr); 00999 01000 ret = ibuf_bitmap_page_get_bits(bitmap_page, page_no, IBUF_BITMAP_IBUF, 01001 &mtr); 01002 mtr_commit(&mtr); 01003 01004 return(ret); 01005 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1011 of file ibuf0ibuf.c.
References FALSE, ibuf_bitmap_get_map_page(), IBUF_BITMAP_IBUF, ibuf_bitmap_page_get_bits(), ibuf_fixed_addr_page(), page_t, and TRUE.
Referenced by buf_page_init_for_read().
01013 : TRUE if level 2 or level 3 page */ 01014 ulint space, /* in: space id */ 01015 ulint page_no,/* in: page number */ 01016 mtr_t* mtr) /* in: mtr which will contain an x-latch to the 01017 bitmap page if the page is not one of the fixed 01018 address ibuf pages */ 01019 { 01020 page_t* bitmap_page; 01021 ibool ret; 01022 01023 #ifdef UNIV_LOG_DEBUG 01024 if (space % 2 != 0) { 01025 01026 fputs("No ibuf in a replicate space\n", stderr); 01027 01028 return(FALSE); 01029 } 01030 #endif 01031 if (ibuf_fixed_addr_page(space, page_no)) { 01032 01033 return(TRUE); 01034 } 01035 01036 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, mtr); 01037 01038 ret = ibuf_bitmap_page_get_bits(bitmap_page, page_no, IBUF_BITMAP_IBUF, 01039 mtr); 01040 return(ret); 01041 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* ibuf_parse_bitmap_init | ( | byte * | ptr, | |
| byte *end_ptr | __attribute__((unused)), | |||
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 593 of file ibuf0ibuf.c.
References ibuf_bitmap_page_init(), and ut_ad.
Referenced by recv_parse_or_apply_log_rec_body().
00595 : end of log record or NULL */ 00596 byte* ptr, /* in: buffer */ 00597 byte* end_ptr __attribute__((unused)), /* in: buffer end */ 00598 page_t* page, /* in: page or NULL */ 00599 mtr_t* mtr) /* in: mtr or NULL */ 00600 { 00601 ut_ad(ptr && end_ptr); 00602 00603 if (page) { 00604 ibuf_bitmap_page_init(page, mtr); 00605 } 00606 00607 return(ptr); 00608 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void ibuf_print | ( | FILE * | file | ) |
Definition at line 3506 of file ibuf0ibuf.c.
References data, ibuf, ibuf_mutex, mutex_enter, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by srv_printf_innodb_monitor().
03508 : file where to print */ 03509 { 03510 ibuf_data_t* data; 03511 #ifdef UNIV_IBUF_DEBUG 03512 ulint i; 03513 #endif 03514 03515 mutex_enter(&ibuf_mutex); 03516 03517 data = UT_LIST_GET_FIRST(ibuf->data_list); 03518 03519 while (data) { 03520 fprintf(file, 03521 "Ibuf for space %lu: size %lu, free list len %lu, seg size %lu,", 03522 (ulong) data->space, (ulong) data->size, 03523 (ulong) data->free_list_len, 03524 (ulong) data->seg_size); 03525 03526 if (data->empty) { 03527 fputs(" is empty\n", file); 03528 } else { 03529 fputs(" is not empty\n", file); 03530 } 03531 fprintf(file, 03532 "Ibuf for space %lu: size %lu, free list len %lu, seg size %lu,\n" 03533 "%lu inserts, %lu merged recs, %lu merges\n", 03534 (ulong) data->space, 03535 (ulong) data->size, 03536 (ulong) data->free_list_len, 03537 (ulong) data->seg_size, 03538 (ulong) data->n_inserts, 03539 (ulong) data->n_merged_recs, 03540 (ulong) data->n_merges); 03541 #ifdef UNIV_IBUF_DEBUG 03542 for (i = 0; i < IBUF_COUNT_N_PAGES; i++) { 03543 if (ibuf_count_get(data->space, i) > 0) { 03544 03545 fprintf(stderr, 03546 "Ibuf count for page %lu is %lu\n", 03547 (ulong) i, 03548 (ulong) ibuf_count_get(data->space, i)); 03549 } 03550 } 03551 #endif 03552 data = UT_LIST_GET_NEXT(data_list, data); 03553 } 03554 03555 mutex_exit(&ibuf_mutex); 03556 }
Here is the caller graph for this function:

Definition at line 1047 of file ibuf0ibuf.c.
References ibuf_inside(), mach_read_from_4(), rec_get_n_fields_old(), rec_get_nth_field_old(), trx_doublewrite_must_reset_space_ids, trx_sys_multiple_tablespace_format, ut_a, and ut_ad.
Referenced by ibuf_delete_for_discarded_space(), ibuf_get_merge_page_nos(), ibuf_get_volume_buffered(), and ibuf_merge_or_delete_for_page().
01049 : page number */ 01050 rec_t* rec) /* in: ibuf record */ 01051 { 01052 byte* field; 01053 ulint len; 01054 01055 ut_ad(ibuf_inside()); 01056 ut_ad(rec_get_n_fields_old(rec) > 2); 01057 01058 field = rec_get_nth_field_old(rec, 1, &len); 01059 01060 if (len == 1) { 01061 /* This is of the >= 4.1.x record format */ 01062 ut_a(trx_sys_multiple_tablespace_format); 01063 01064 field = rec_get_nth_field_old(rec, 2, &len); 01065 } else { 01066 ut_a(trx_doublewrite_must_reset_space_ids); 01067 ut_a(!trx_sys_multiple_tablespace_format); 01068 01069 field = rec_get_nth_field_old(rec, 0, &len); 01070 } 01071 01072 ut_a(len == 4); 01073 01074 return(mach_read_from_4(field)); 01075 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1082 of file ibuf0ibuf.c.
References ibuf_inside(), mach_read_from_4(), rec_get_n_fields_old(), rec_get_nth_field_old(), trx_doublewrite_must_reset_space_ids, trx_sys_multiple_tablespace_format, ut_a, and ut_ad.
Referenced by ibuf_delete_for_discarded_space(), ibuf_get_merge_page_nos(), ibuf_get_volume_buffered(), and ibuf_merge_or_delete_for_page().
01084 : space id */ 01085 rec_t* rec) /* in: ibuf record */ 01086 { 01087 byte* field; 01088 ulint len; 01089 01090 ut_ad(ibuf_inside()); 01091 ut_ad(rec_get_n_fields_old(rec) > 2); 01092 01093 field = rec_get_nth_field_old(rec, 1, &len); 01094 01095 if (len == 1) { 01096 /* This is of the >= 4.1.x record format */ 01097 01098 ut_a(trx_sys_multiple_tablespace_format); 01099 field = rec_get_nth_field_old(rec, 0, &len); 01100 ut_a(len == 4); 01101 01102 return(mach_read_from_4(field)); 01103 } 01104 01105 ut_a(trx_doublewrite_must_reset_space_ids); 01106 ut_a(!trx_sys_multiple_tablespace_format); 01107 01108 return(0); 01109 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1277 of file ibuf0ibuf.c.
References data, DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE, DATA_ORDER_NULL_TYPE_BUF_SIZE, dtype_get_sql_null_size(), dtype_new_read_for_order_and_null_size(), dtype_read_for_order_and_null_size(), FALSE, ibuf_build_entry_from_ibuf_rec(), ibuf_dummy_index_free(), ibuf_inside(), mem_heap_create, mem_heap_free, page_dir_calc_reserved_space(), rec_get_converted_extra_size(), rec_get_converted_size(), rec_get_n_fields_old(), rec_get_nth_field_old(), TRUE, trx_doublewrite_must_reset_space_ids, trx_sys_multiple_tablespace_format, ut_a, and ut_ad.
Referenced by ibuf_get_merge_page_nos(), and ibuf_get_volume_buffered().
01279 : size of index record in bytes + an upper 01280 limit of the space taken in the page directory */ 01281 rec_t* ibuf_rec)/* in: ibuf record */ 01282 { 01283 dtype_t dtype; 01284 ibool new_format = FALSE; 01285 ulint data_size = 0; 01286 ulint n_fields; 01287 byte* types; 01288 byte* data; 01289 ulint len; 01290 ulint i; 01291 01292 ut_ad(ibuf_inside()); 01293 ut_ad(rec_get_n_fields_old(ibuf_rec) > 2); 01294 01295 data = rec_get_nth_field_old(ibuf_rec, 1, &len); 01296 01297 if (len > 1) { 01298 /* < 4.1.x format record */ 01299 01300 ut_a(trx_doublewrite_must_reset_space_ids); 01301 ut_a(!trx_sys_multiple_tablespace_format); 01302 01303 n_fields = rec_get_n_fields_old(ibuf_rec) - 2; 01304 01305 types = rec_get_nth_field_old(ibuf_rec, 1, &len); 01306 01307 ut_ad(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE); 01308 } else { 01309 /* >= 4.1.x format record */ 01310 01311 ut_a(trx_sys_multiple_tablespace_format); 01312 ut_a(*data == 0); 01313 01314 types = rec_get_nth_field_old(ibuf_rec, 3, &len); 01315 01316 ut_a(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE <= 1); 01317 if (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) { 01318 /* compact record format */ 01319 ulint volume; 01320 dict_index_t* dummy_index; 01321 mem_heap_t* heap = mem_heap_create(500); 01322 dtuple_t* entry = 01323 ibuf_build_entry_from_ibuf_rec( 01324 ibuf_rec, heap, &dummy_index); 01325 volume = rec_get_converted_size(dummy_index, entry); 01326 ibuf_dummy_index_free(dummy_index); 01327 mem_heap_free(heap); 01328 return(volume + page_dir_calc_reserved_space(1)); 01329 } 01330 01331 n_fields = rec_get_n_fields_old(ibuf_rec) - 4; 01332 01333 new_format = TRUE; 01334 } 01335 01336 for (i = 0; i < n_fields; i++) { 01337 if (new_format) { 01338 data = rec_get_nth_field_old(ibuf_rec, i + 4, &len); 01339 01340 dtype_new_read_for_order_and_null_size(&dtype, 01341 types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE); 01342 } else { 01343 data = rec_get_nth_field_old(ibuf_rec, i + 2, &len); 01344 01345 dtype_read_for_order_and_null_size(&dtype, 01346 types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE); 01347 } 01348 01349 if (len == UNIV_SQL_NULL) { 01350 data_size += dtype_get_sql_null_size(&dtype); 01351 } else { 01352 data_size += len; 01353 } 01354 } 01355 01356 return(data_size + rec_get_converted_extra_size(data_size, n_fields) 01357 + page_dir_calc_reserved_space(1)); 01358 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void ibuf_remove_free_page | ( | ulint | space, | |
| ibuf_data_t * | ibuf_data | |||
| ) | [static] |
Definition at line 1709 of file ibuf0ibuf.c.
References buf_page_get, buf_page_reset_file_page_was_freed(), buf_page_set_file_page_was_freed(), FALSE, fil_space_get_latch(), flst_get_last(), flst_remove(), fseg_free_page(), ibuf_bitmap_get_map_page(), IBUF_BITMAP_IBUF, ibuf_bitmap_page_set_bits(), ibuf_data_too_much_free(), ibuf_enter(), ibuf_exit(), IBUF_HEADER, ibuf_header_page_get(), ibuf_mutex, ibuf_pessimistic_insert_mutex, ibuf_tree_root_get(), IBUF_TREE_SEG_HEADER, mtr_commit(), mtr_start(), mtr_x_lock, mutex_enter, mutex_exit(), fil_addr_struct::page, PAGE_BTR_IBUF_FREE_LIST, PAGE_BTR_IBUF_FREE_LIST_NODE, PAGE_HEADER, page_t, RW_X_LATCH, SYNC_TREE_NODE, ut_a, and ut_ad.
Referenced by ibuf_free_excess_pages().
01711 : space id */ 01712 ibuf_data_t* ibuf_data) /* in: ibuf data for the space */ 01713 { 01714 mtr_t mtr; 01715 mtr_t mtr2; 01716 page_t* header_page; 01717 ulint page_no; 01718 page_t* page; 01719 page_t* root; 01720 page_t* bitmap_page; 01721 01722 ut_a(space == 0); 01723 01724 mtr_start(&mtr); 01725 01726 /* Acquire the fsp latch before the ibuf header, obeying the latching 01727 order */ 01728 mtr_x_lock(fil_space_get_latch(space), &mtr); 01729 01730 header_page = ibuf_header_page_get(space, &mtr); 01731 01732 /* Prevent pessimistic inserts to insert buffer trees for a while */ 01733 mutex_enter(&ibuf_pessimistic_insert_mutex); 01734 01735 ibuf_enter(); 01736 01737 mutex_enter(&ibuf_mutex); 01738 01739 if (!ibuf_data_too_much_free(ibuf_data)) { 01740 01741 mutex_exit(&ibuf_mutex); 01742 01743 ibuf_exit(); 01744 01745 mutex_exit(&ibuf_pessimistic_insert_mutex); 01746 01747 mtr_commit(&mtr); 01748 01749 return; 01750 } 01751 01752 mtr_start(&mtr2); 01753 01754 root = ibuf_tree_root_get(ibuf_data, space, &mtr2); 01755 01756 page_no = flst_get_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, 01757 &mtr2) 01758 .page; 01759 01760 /* NOTE that we must release the latch on the ibuf tree root 01761 because in fseg_free_page we access level 1 pages, and the root 01762 is a level 2 page. */ 01763 01764 mtr_commit(&mtr2); 01765 mutex_exit(&ibuf_mutex); 01766 01767 ibuf_exit(); 01768 01769 /* Since pessimistic inserts were prevented, we know that the 01770 page is still in the free list. NOTE that also deletes may take 01771 pages from the free list, but they take them from the start, and 01772 the free list was so long that they cannot have taken the last 01773 page from it. */ 01774 01775 fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 01776 space, page_no, &mtr); 01777 #ifdef UNIV_DEBUG_FILE_ACCESSES 01778 buf_page_reset_file_page_was_freed(space, page_no); 01779 #endif 01780 ibuf_enter(); 01781 01782 mutex_enter(&ibuf_mutex); 01783 01784 root = ibuf_tree_root_get(ibuf_data, space, &mtr); 01785 01786 ut_ad(page_no == flst_get_last(root + PAGE_HEADER 01787 + PAGE_BTR_IBUF_FREE_LIST, &mtr) 01788 .page); 01789 01790 page = buf_page_get(space, page_no, RW_X_LATCH, &mtr); 01791 01792 #ifdef UNIV_SYNC_DEBUG 01793 buf_page_dbg_add_level(page, SYNC_TREE_NODE); 01794 #endif /* UNIV_SYNC_DEBUG */ 01795 01796 /* Remove the page from the free list and update the ibuf size data */ 01797 01798 flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, 01799 page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr); 01800 01801 ibuf_data->seg_size--; 01802 ibuf_data->free_list_len--; 01803 01804 mutex_exit(&ibuf_pessimistic_insert_mutex); 01805 01806 /* Set the bit indicating that this page is no more an ibuf tree page 01807 (level 2 page) */ 01808 01809 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, &mtr); 01810 01811 ibuf_bitmap_page_set_bits(bitmap_page, page_no, IBUF_BITMAP_IBUF, 01812 FALSE, &mtr); 01813 #ifdef UNIV_DEBUG_FILE_ACCESSES 01814 buf_page_set_file_page_was_freed(space, page_no); 01815 #endif 01816 mtr_commit(&mtr); 01817 01818 mutex_exit(&ibuf_mutex); 01819 01820 ibuf_exit(); 01821 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void ibuf_reset_free_bits | ( | dict_index_t * | index, | |
| page_t * | page | |||
| ) |
Definition at line 879 of file ibuf0ibuf.c.
References ibuf_set_free_bits(), and index().
Referenced by btr_discard_only_page_on_level(), btr_lift_page_up(), btr_page_split_and_insert(), and btr_root_raise_and_insert().
00881 : index */ 00882 page_t* page) /* in: index page; free bits are set to 0 if 00883 the index is non-clustered and non-unique and 00884 the page level is 0 */ 00885 { 00886 ibuf_set_free_bits(index->type, page, 0, ULINT_UNDEFINED); 00887 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 862 of file ibuf0ibuf.c.
References ibuf_set_free_bits().
Referenced by btr_create().
00864 : index type */ 00865 page_t* page) /* in: index page; free bits are set to 0 if the index 00866 is non-clustered and non-unique and the page level is 00867 0 */ 00868 { 00869 ibuf_set_free_bits(type, page, 0, ULINT_UNDEFINED); 00870 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static dtuple_t* ibuf_search_tuple_build | ( | ulint | space, | |
| ulint | page_no, | |||
| mem_heap_t * | heap | |||
| ) | [static] |
Definition at line 1481 of file ibuf0ibuf.c.
References buf, dfield_set_data(), dtuple_create(), dtuple_get_nth_field(), dtuple_set_types_binary(), mach_write_to_4(), mem_heap_alloc(), trx_doublewrite_must_reset_space_ids, trx_sys_multiple_tablespace_format, and ut_a.
Referenced by ibuf_merge_or_delete_for_page().
01483 : search tuple */ 01484 ulint space, /* in: space id */ 01485 ulint page_no,/* in: index page number */ 01486 mem_heap_t* heap) /* in: heap into which to build */ 01487 { 01488 dtuple_t* tuple; 01489 dfield_t* field; 01490 byte* buf; 01491 01492 ut_a(space == 0); 01493 ut_a(trx_doublewrite_must_reset_space_ids); 01494 ut_a(!trx_sys_multiple_tablespace_format); 01495 01496 tuple = dtuple_create(heap, 1); 01497 01498 /* Store the page number in tuple */ 01499 01500 field = dtuple_get_nth_field(tuple, 0); 01501 01502 buf = mem_heap_alloc(heap, 4); 01503 01504 mach_write_to_4(buf, page_no); 01505 01506 dfield_set_data(field, buf, 4); 01507 01508 dtuple_set_types_binary(tuple, 1); 01509 01510 return(tuple); 01511 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 799 of file ibuf0ibuf.c.
References btr_page_get_level_low(), buf_frame_get_page_no(), buf_frame_get_space_id(), DICT_CLUSTERED, IBUF_BITMAP_FREE, ibuf_bitmap_get_map_page(), ibuf_bitmap_page_get_bits(), ibuf_bitmap_page_set_bits(), mtr_commit(), mtr_start(), page_t, and ut_a.
Referenced by ibuf_reset_free_bits(), and ibuf_reset_free_bits_with_type().
00801 : index type */ 00802 page_t* page, /* in: index page; free bit is set if the index is 00803 non-clustered and page level is 0 */ 00804 ulint val, /* in: value to set: < 4 */ 00805 ulint max_val)/* in: ULINT_UNDEFINED or a maximum value which 00806 the bits must have before setting; this is for 00807 debugging */ 00808 { 00809 mtr_t mtr; 00810 page_t* bitmap_page; 00811 00812 if (type & DICT_CLUSTERED) { 00813 00814 return; 00815 } 00816 00817 if (btr_page_get_level_low(page) != 0) { 00818 00819 return; 00820 } 00821 00822 mtr_start(&mtr); 00823 00824 bitmap_page = ibuf_bitmap_get_map_page(buf_frame_get_space_id(page), 00825 buf_frame_get_page_no(page), &mtr); 00826 00827 if (max_val != ULINT_UNDEFINED) { 00828 #ifdef UNIV_IBUF_DEBUG 00829 ulint old_val; 00830 00831 old_val = ibuf_bitmap_page_get_bits(bitmap_page, 00832 buf_frame_get_page_no(page), 00833 IBUF_BITMAP_FREE, &mtr); 00834 if (old_val != max_val) { 00835 /* fprintf(stderr, 00836 "Ibuf: page %lu old val %lu max val %lu\n", 00837 buf_frame_get_page_no(page), old_val, max_val); */ 00838 } 00839 00840 ut_a(old_val <= max_val); 00841 #endif 00842 } 00843 #ifdef UNIV_IBUF_DEBUG 00844 /* fprintf(stderr, "Setting page no %lu free bits to %lu should be %lu\n", 00845 buf_frame_get_page_no(page), val, 00846 ibuf_index_page_calc_free(page)); */ 00847 00848 ut_a(val <= ibuf_index_page_calc_free(page)); 00849 #endif 00850 ibuf_bitmap_page_set_bits(bitmap_page, buf_frame_get_page_no(page), 00851 IBUF_BITMAP_FREE, val, &mtr); 00852 mtr_commit(&mtr); 00853 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 757 of file ibuf0ibuf.c.
References btr_page_get_level_low(), buf_frame_get_page_no(), buf_frame_get_space_id(), DICT_CLUSTERED, IBUF_BITMAP_FREE, ibuf_bitmap_get_map_page(), ibuf_bitmap_page_set_bits(), page_t, and ut_a.
Referenced by ibuf_update_free_bits_for_two_pages_low(), and ibuf_update_free_bits_low().
00759 : index type */ 00760 page_t* page, /* in: index page; free bit is set if the index is 00761 non-clustered and page level is 0 */ 00762 ulint val, /* in: value to set: < 4 */ 00763 mtr_t* mtr) /* in: mtr */ 00764 { 00765 page_t* bitmap_page; 00766 00767 if (type & DICT_CLUSTERED) { 00768 00769 return; 00770 } 00771 00772 if (btr_page_get_level_low(page) != 0) { 00773 00774 return; 00775 } 00776 00777 bitmap_page = ibuf_bitmap_get_map_page(buf_frame_get_space_id(page), 00778 buf_frame_get_page_no(page), mtr); 00779 #ifdef UNIV_IBUF_DEBUG 00780 /* fprintf(stderr, 00781 "Setting page no %lu free bits to %lu should be %lu\n", 00782 buf_frame_get_page_no(page), val, 00783 ibuf_index_page_calc_free(page)); */ 00784 00785 ut_a(val <= ibuf_index_page_calc_free(page)); 00786 #endif 00787 ibuf_bitmap_page_set_bits(bitmap_page, buf_frame_get_page_no(page), 00788 IBUF_BITMAP_FREE, val, mtr); 00789 00790 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static page_t* ibuf_tree_root_get | ( | ibuf_data_t * | data, | |
| ulint | space, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 296 of file ibuf0ibuf.c.
References buf_page_get, dict_tree_get_lock(), FSP_IBUF_TREE_ROOT_PAGE_NO, ibuf_inside(), mtr_x_lock, page, page_t, RW_X_LATCH, SYNC_TREE_NODE, ut_a, and ut_ad.
Referenced by ibuf_add_free_page(), ibuf_delete_rec(), ibuf_insert_low(), ibuf_is_empty(), and ibuf_remove_free_page().
00298 : insert buffer tree root page */ 00299 ibuf_data_t* data, /* in: ibuf data */ 00300 ulint space, /* in: space id */ 00301 mtr_t* mtr) /* in: mtr */ 00302 { 00303 page_t* page; 00304 00305 ut_a(space == 0); 00306 ut_ad(ibuf_inside()); 00307 00308 mtr_x_lock(dict_tree_get_lock((data->index)->tree), mtr); 00309 00310 page = buf_page_get(space, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, 00311 mtr); 00312 #ifdef UNIV_SYNC_DEBUG 00313 buf_page_dbg_add_level(page, SYNC_TREE_NODE); 00314 #endif /* UNIV_SYNC_DEBUG */ 00315 00316 return(page); 00317 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void ibuf_update_free_bits_for_two_pages_low | ( | dict_index_t * | index, | |
| page_t * | page1, | |||
| page_t * | page2, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 922 of file ibuf0ibuf.c.
References ibuf_bitmap_mutex, ibuf_set_free_bits_low(), index(), mutex_enter, and mutex_exit().
Referenced by btr_page_split_and_insert().
00924 : index */ 00925 page_t* page1, /* in: index page */ 00926 page_t* page2, /* in: index page */ 00927 mtr_t* mtr) /* in: mtr */ 00928 { 00929 ulint state; 00930 00931 /* As we have to x-latch two random bitmap pages, we have to acquire 00932 the bitmap mutex to prevent a deadlock with a similar operation 00933 performed by another OS thread. */ 00934 00935 mutex_enter(&ibuf_bitmap_mutex); 00936 00937 state = ibuf_index_page_calc_free(page1); 00938 00939 ibuf_set_free_bits_low(index->type, page1, state, mtr); 00940 00941 state = ibuf_index_page_calc_free(page2); 00942 00943 ibuf_set_free_bits_low(index->type, page2, state, mtr); 00944 00945 mutex_exit(&ibuf_bitmap_mutex); 00946 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void ibuf_update_free_bits_low | ( | dict_index_t * | index, | |
| page_t * | page, | |||
| ulint | max_ins_size, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 895 of file ibuf0ibuf.c.
References ibuf_set_free_bits_low(), and index().
Referenced by btr_cur_optimistic_delete().
00897 : index */ 00898 page_t* page, /* in: index page */ 00899 ulint max_ins_size, /* in: value of maximum insert size 00900 with reorganize before the latest 00901 operation performed to the page */ 00902 mtr_t* mtr) /* in: mtr */ 00903 { 00904 ulint before; 00905 ulint after; 00906 00907 before = ibuf_index_page_calc_free_bits(max_ins_size); 00908 00909 after = ibuf_index_page_calc_free(page); 00910 00911 if (before != after) { 00912 ibuf_set_free_bits_low(index->type, page, after, mtr); 00913 } 00914 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void ibuf_update_max_tablespace_id | ( | void | ) |
Definition at line 2449 of file ibuf0ibuf.c.
References btr_pcur_get_rec(), btr_pcur_is_before_first_on_page(), btr_pcur_move_to_prev(), btr_pcur_open_at_index_side(), BTR_SEARCH_LEAF, dict_table_is_comp(), FALSE, fil_set_max_space_id_if_bigger(), fil_space_get_ibuf_data(), ibuf_enter(), ibuf_exit(), mach_read_from_4(), mtr_commit(), mtr_start(), rec_get_nth_field_old(), dict_index_struct::table, TRUE, and ut_a.
Referenced by innobase_start_or_create_for_mysql().
02451 { 02452 ulint max_space_id; 02453 rec_t* rec; 02454 byte* field; 02455 ulint len; 02456 ibuf_data_t* ibuf_data; 02457 dict_index_t* ibuf_index; 02458 btr_pcur_t pcur; 02459 mtr_t mtr; 02460 02461 ibuf_data = fil_space_get_ibuf_data(0); 02462 02463 ibuf_index = ibuf_data->index; 02464 ut_a(!dict_table_is_comp(ibuf_index->table)); 02465 02466 ibuf_enter(); 02467 02468 mtr_start(&mtr); 02469 02470 btr_pcur_open_at_index_side(FALSE, ibuf_index, BTR_SEARCH_LEAF, 02471 &pcur, TRUE, &mtr); 02472 btr_pcur_move_to_prev(&pcur, &mtr); 02473 02474 if (btr_pcur_is_before_first_on_page(&pcur, &mtr)) { 02475 /* The tree is empty */ 02476 02477 max_space_id = 0; 02478 } else { 02479 rec = btr_pcur_get_rec(&pcur); 02480 02481 field = rec_get_nth_field_old(rec, 0, &len); 02482 02483 ut_a(len == 4); 02484 02485 max_space_id = mach_read_from_4(field); 02486 } 02487 02488 mtr_commit(&mtr); 02489 ibuf_exit(); 02490 02491 /* printf("Maximum space id in insert buffer %lu\n", max_space_id); */ 02492 02493 fil_set_max_space_id_if_bigger(max_space_id); 02494 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool ibuf_validate_low | ( | void | ) |
Definition at line 3426 of file ibuf0ibuf.c.
References data, ibuf, ibuf_mutex, TRUE, ut_a, ut_ad, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by ibuf_contract_ext(), ibuf_delete_rec(), and ibuf_insert_low().
03428 : TRUE if ok */ 03429 { 03430 ibuf_data_t* data; 03431 ulint sum_sizes; 03432 03433 #ifdef UNIV_SYNC_DEBUG 03434 ut_ad(mutex_own(&ibuf_mutex)); 03435 #endif /* UNIV_SYNC_DEBUG */ 03436 03437 sum_sizes = 0; 03438 03439 data = UT_LIST_GET_FIRST(ibuf->data_list); 03440 03441 while (data) { 03442 sum_sizes += data->size; 03443 03444 data = UT_LIST_GET_NEXT(data_list, data); 03445 } 03446 03447 ut_a(sum_sizes == ibuf->size); 03448 03449 return(TRUE); 03450 }
Here is the caller graph for this function:

Definition at line 141 of file ibuf0ibuf.c.
Referenced by ibuf_contract_after_insert(), ibuf_contract_ext(), ibuf_data_init_for_space(), ibuf_data_sizes_update(), ibuf_init_at_db_start(), ibuf_insert_low(), ibuf_is_empty(), ibuf_print(), and ibuf_validate_low().
mutex_t ibuf_bitmap_mutex [static] |
Definition at line 181 of file ibuf0ibuf.c.
Referenced by ibuf_init_at_db_start(), and ibuf_update_free_bits_for_two_pages_low().
Definition at line 145 of file ibuf0ibuf.c.
mutex_t ibuf_mutex [static] |
Definition at line 178 of file ibuf0ibuf.c.
Referenced by ibuf_add_free_page(), ibuf_contract_after_insert(), ibuf_contract_ext(), ibuf_data_enough_free_for_insert(), ibuf_data_init_for_space(), ibuf_data_sizes_update(), ibuf_data_too_much_free(), ibuf_delete_for_discarded_space(), ibuf_delete_rec(), ibuf_free_excess_pages(), ibuf_init_at_db_start(), ibuf_insert_low(), ibuf_is_empty(), ibuf_merge_or_delete_for_page(), ibuf_print(), ibuf_remove_free_page(), and ibuf_validate_low().
mutex_t ibuf_pessimistic_insert_mutex [static] |
Definition at line 175 of file ibuf0ibuf.c.
Referenced by ibuf_init_at_db_start(), ibuf_insert_low(), and ibuf_remove_free_page().
1.4.7

